mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
refactor: Differentiate pubspec and resolution errors for plugins (#142035)
Part of #137040 and #80374 - Differentiate pubspec and resolution errors - Rename platform to platformKey - Add TODO for rework logic of flag [throwOnPluginPubspecError] - Swap for loop: handle by platform and then by plugin
This commit is contained in:
parent
9d5380889d
commit
b4f925e85a
@ -1237,20 +1237,22 @@ bool hasPlugins(FlutterProject project) {
|
||||
///
|
||||
/// For more details, https://flutter.dev/go/federated-plugins.
|
||||
// TODO(stuartmorgan): Expand implementation to apply to all implementations,
|
||||
// not just Dart-only, per the federated plugin spec.
|
||||
// not just Dart-only, per the federated plugin spec.
|
||||
// TODO(gustl22): The flag [throwOnPluginPubspecError] is currently only used
|
||||
// for testing dart plugins as the logic is not working correctly.
|
||||
List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
List<Plugin> plugins, {
|
||||
bool throwOnPluginPubspecError = true,
|
||||
}) {
|
||||
final List<String> platforms = <String>[
|
||||
const Iterable<String> platformKeys = <String>[
|
||||
AndroidPlugin.kConfigKey,
|
||||
IOSPlugin.kConfigKey,
|
||||
LinuxPlugin.kConfigKey,
|
||||
MacOSPlugin.kConfigKey,
|
||||
WindowsPlugin.kConfigKey,
|
||||
];
|
||||
final Map<String, List<PluginInterfaceResolution>> possibleResolutions
|
||||
= <String, List<PluginInterfaceResolution>>{};
|
||||
final Map<String, List<PluginInterfaceResolution>> possibleResolutions =
|
||||
<String, List<PluginInterfaceResolution>>{};
|
||||
final Map<String, String> defaultImplementations = <String, String>{};
|
||||
// Generates a key for the maps above.
|
||||
String getResolutionKey({required String platform, required String packageName}) {
|
||||
@ -1258,18 +1260,19 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
}
|
||||
|
||||
bool hasPubspecError = false;
|
||||
for (final Plugin plugin in plugins) {
|
||||
for (final String platform in platforms) {
|
||||
if (plugin.platforms[platform] == null &&
|
||||
plugin.defaultPackagePlatforms[platform] == null) {
|
||||
for (final String platformKey in platformKeys) {
|
||||
for (final Plugin plugin in plugins) {
|
||||
if (plugin.platforms[platformKey] == null &&
|
||||
plugin.defaultPackagePlatforms[platformKey] == null) {
|
||||
// The plugin doesn't implement this platform.
|
||||
continue;
|
||||
}
|
||||
String? implementsPackage = plugin.implementsPackage;
|
||||
if (implementsPackage == null || implementsPackage.isEmpty) {
|
||||
final String? defaultImplementation = plugin.defaultPackagePlatforms[platform];
|
||||
final String? defaultImplementation =
|
||||
plugin.defaultPackagePlatforms[platformKey];
|
||||
final bool hasInlineDartImplementation =
|
||||
plugin.pluginDartClassPlatforms[platform] != null;
|
||||
plugin.pluginDartClassPlatforms[platformKey] != null;
|
||||
if (defaultImplementation == null && !hasInlineDartImplementation) {
|
||||
if (throwOnPluginPubspecError) {
|
||||
globals.printError(
|
||||
@ -1279,27 +1282,27 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
'flutter:\n'
|
||||
' plugin:\n'
|
||||
' platforms:\n'
|
||||
' $platform:\n'
|
||||
' $platformKey:\n'
|
||||
' $kDartPluginClass: <plugin-class>\n'
|
||||
'\n'
|
||||
'To set a default implementation, use:\n'
|
||||
'flutter:\n'
|
||||
' plugin:\n'
|
||||
' platforms:\n'
|
||||
' $platform:\n'
|
||||
' $platformKey:\n'
|
||||
' $kDefaultPackage: <plugin-implementation>\n'
|
||||
'\n'
|
||||
'To implement an interface, use:\n'
|
||||
'flutter:\n'
|
||||
' plugin:\n'
|
||||
' implements: <plugin-interface>'
|
||||
'\n'
|
||||
'\n',
|
||||
);
|
||||
}
|
||||
hasPubspecError = true;
|
||||
continue;
|
||||
}
|
||||
final String defaultImplementationKey = getResolutionKey(platform: platform, packageName: plugin.name);
|
||||
final String defaultImplementationKey = getResolutionKey(platform: platformKey, packageName: plugin.name);
|
||||
if (defaultImplementation != null) {
|
||||
defaultImplementations[defaultImplementationKey] = defaultImplementation;
|
||||
continue;
|
||||
@ -1313,7 +1316,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
// - the plugin requires at least Flutter 2.11 (when this opt-in logic
|
||||
// was added), so that existing plugins continue to work.
|
||||
// See https://github.com/flutter/flutter/issues/87862 for details.
|
||||
final bool isDesktop = platform == 'linux' || platform == 'macos' || platform == 'windows';
|
||||
final bool isDesktop = platformKey == 'linux' || platformKey == 'macos' || platformKey == 'windows';
|
||||
final semver.VersionConstraint? flutterConstraint = plugin.flutterConstraint;
|
||||
final semver.Version? minFlutterVersion = flutterConstraint != null &&
|
||||
flutterConstraint is semver.VersionRange ? flutterConstraint.min : null;
|
||||
@ -1330,25 +1333,23 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
}
|
||||
}
|
||||
// If there's no Dart implementation, there's nothing to register.
|
||||
if (plugin.pluginDartClassPlatforms[platform] == null ||
|
||||
plugin.pluginDartClassPlatforms[platform] == 'none') {
|
||||
if (plugin.pluginDartClassPlatforms[platformKey] == null ||
|
||||
plugin.pluginDartClassPlatforms[platformKey] == 'none') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it hasn't been skipped, it's a candidate for auto-registration, so
|
||||
// add it as a possible resolution.
|
||||
final String resolutionKey = getResolutionKey(platform: platform, packageName: implementsPackage);
|
||||
if (!possibleResolutions.containsKey(resolutionKey)) {
|
||||
possibleResolutions[resolutionKey] = <PluginInterfaceResolution>[];
|
||||
}
|
||||
final String resolutionKey = getResolutionKey(platform: platformKey, packageName: implementsPackage);
|
||||
possibleResolutions.putIfAbsent(resolutionKey, () => <PluginInterfaceResolution>[]);
|
||||
possibleResolutions[resolutionKey]!.add(PluginInterfaceResolution(
|
||||
plugin: plugin,
|
||||
platform: platform,
|
||||
platform: platformKey,
|
||||
));
|
||||
}
|
||||
}
|
||||
if (hasPubspecError && throwOnPluginPubspecError) {
|
||||
throwToolExit('Please resolve the errors');
|
||||
throwToolExit('Please resolve the pubspec errors');
|
||||
}
|
||||
|
||||
// Now resolve all the possible resolutions to a single option for each
|
||||
@ -1401,7 +1402,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
}
|
||||
}
|
||||
if (hasResolutionError) {
|
||||
throwToolExit('Please resolve the errors');
|
||||
throwToolExit('Please resolve the plugin implementation selection errors');
|
||||
}
|
||||
return finalResolution;
|
||||
}
|
||||
|
@ -95,6 +95,63 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext(
|
||||
'selects uncontested implementation from direct dependency with additional native implementation',
|
||||
() async {
|
||||
final Set<String> directDependencies = <String>{
|
||||
'url_launcher_linux',
|
||||
'url_launcher_macos',
|
||||
};
|
||||
final List<PluginInterfaceResolution> resolutions =
|
||||
resolvePlatformImplementation(
|
||||
<Plugin>[
|
||||
// Following plugin is native only and is not resolved as a dart plugin:
|
||||
Plugin.fromYaml(
|
||||
'url_launcher_linux',
|
||||
'',
|
||||
YamlMap.wrap(<String, dynamic>{
|
||||
'platforms': <String, dynamic>{
|
||||
'linux': <String, dynamic>{
|
||||
'package': 'com.example.url_launcher',
|
||||
'pluginClass': 'UrlLauncherPluginLinux',
|
||||
},
|
||||
},
|
||||
}),
|
||||
null,
|
||||
<String>[],
|
||||
fileSystem: fs,
|
||||
appDependencies: directDependencies,
|
||||
),
|
||||
Plugin.fromYaml(
|
||||
'url_launcher_macos',
|
||||
'',
|
||||
YamlMap.wrap(<String, dynamic>{
|
||||
'implements': 'url_launcher',
|
||||
'platforms': <String, dynamic>{
|
||||
'macos': <String, dynamic>{
|
||||
'dartPluginClass': 'UrlLauncherPluginMacOS',
|
||||
},
|
||||
},
|
||||
}),
|
||||
null,
|
||||
<String>[],
|
||||
fileSystem: fs,
|
||||
appDependencies: directDependencies,
|
||||
),
|
||||
],
|
||||
throwOnPluginPubspecError: false,
|
||||
);
|
||||
|
||||
expect(resolutions.length, equals(1));
|
||||
expect(
|
||||
resolutions[0].toMap(),
|
||||
equals(<String, String>{
|
||||
'pluginName': 'url_launcher_macos',
|
||||
'dartClass': 'UrlLauncherPluginMacOS',
|
||||
'platform': 'macos',
|
||||
}));
|
||||
});
|
||||
|
||||
testWithoutContext('selects uncontested implementation from transitive dependency', () async {
|
||||
final Set<String> directDependencies = <String>{
|
||||
'url_launcher_macos',
|
||||
@ -538,7 +595,7 @@ void main() {
|
||||
|
||||
},
|
||||
throwsToolExit(
|
||||
message: 'Please resolve the errors',
|
||||
message: 'Please resolve the plugin implementation selection errors',
|
||||
));
|
||||
|
||||
expect(
|
||||
@ -627,7 +684,7 @@ void main() {
|
||||
]);
|
||||
},
|
||||
throwsToolExit(
|
||||
message: 'Please resolve the errors',
|
||||
message: 'Please resolve the plugin implementation selection errors',
|
||||
));
|
||||
|
||||
expect(
|
||||
@ -684,7 +741,7 @@ void main() {
|
||||
]);
|
||||
},
|
||||
throwsToolExit(
|
||||
message: 'Please resolve the errors',
|
||||
message: 'Please resolve the plugin implementation selection errors',
|
||||
));
|
||||
|
||||
expect(
|
||||
|
Loading…
Reference in New Issue
Block a user