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.
|
/// For more details, https://flutter.dev/go/federated-plugins.
|
||||||
// TODO(stuartmorgan): Expand implementation to apply to all implementations,
|
// 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<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||||
List<Plugin> plugins, {
|
List<Plugin> plugins, {
|
||||||
bool throwOnPluginPubspecError = true,
|
bool throwOnPluginPubspecError = true,
|
||||||
}) {
|
}) {
|
||||||
final List<String> platforms = <String>[
|
const Iterable<String> platformKeys = <String>[
|
||||||
AndroidPlugin.kConfigKey,
|
AndroidPlugin.kConfigKey,
|
||||||
IOSPlugin.kConfigKey,
|
IOSPlugin.kConfigKey,
|
||||||
LinuxPlugin.kConfigKey,
|
LinuxPlugin.kConfigKey,
|
||||||
MacOSPlugin.kConfigKey,
|
MacOSPlugin.kConfigKey,
|
||||||
WindowsPlugin.kConfigKey,
|
WindowsPlugin.kConfigKey,
|
||||||
];
|
];
|
||||||
final Map<String, List<PluginInterfaceResolution>> possibleResolutions
|
final Map<String, List<PluginInterfaceResolution>> possibleResolutions =
|
||||||
= <String, List<PluginInterfaceResolution>>{};
|
<String, List<PluginInterfaceResolution>>{};
|
||||||
final Map<String, String> defaultImplementations = <String, String>{};
|
final Map<String, String> defaultImplementations = <String, String>{};
|
||||||
// Generates a key for the maps above.
|
// Generates a key for the maps above.
|
||||||
String getResolutionKey({required String platform, required String packageName}) {
|
String getResolutionKey({required String platform, required String packageName}) {
|
||||||
@ -1258,18 +1260,19 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool hasPubspecError = false;
|
bool hasPubspecError = false;
|
||||||
for (final Plugin plugin in plugins) {
|
for (final String platformKey in platformKeys) {
|
||||||
for (final String platform in platforms) {
|
for (final Plugin plugin in plugins) {
|
||||||
if (plugin.platforms[platform] == null &&
|
if (plugin.platforms[platformKey] == null &&
|
||||||
plugin.defaultPackagePlatforms[platform] == null) {
|
plugin.defaultPackagePlatforms[platformKey] == null) {
|
||||||
// The plugin doesn't implement this platform.
|
// The plugin doesn't implement this platform.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String? implementsPackage = plugin.implementsPackage;
|
String? implementsPackage = plugin.implementsPackage;
|
||||||
if (implementsPackage == null || implementsPackage.isEmpty) {
|
if (implementsPackage == null || implementsPackage.isEmpty) {
|
||||||
final String? defaultImplementation = plugin.defaultPackagePlatforms[platform];
|
final String? defaultImplementation =
|
||||||
|
plugin.defaultPackagePlatforms[platformKey];
|
||||||
final bool hasInlineDartImplementation =
|
final bool hasInlineDartImplementation =
|
||||||
plugin.pluginDartClassPlatforms[platform] != null;
|
plugin.pluginDartClassPlatforms[platformKey] != null;
|
||||||
if (defaultImplementation == null && !hasInlineDartImplementation) {
|
if (defaultImplementation == null && !hasInlineDartImplementation) {
|
||||||
if (throwOnPluginPubspecError) {
|
if (throwOnPluginPubspecError) {
|
||||||
globals.printError(
|
globals.printError(
|
||||||
@ -1279,27 +1282,27 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
|||||||
'flutter:\n'
|
'flutter:\n'
|
||||||
' plugin:\n'
|
' plugin:\n'
|
||||||
' platforms:\n'
|
' platforms:\n'
|
||||||
' $platform:\n'
|
' $platformKey:\n'
|
||||||
' $kDartPluginClass: <plugin-class>\n'
|
' $kDartPluginClass: <plugin-class>\n'
|
||||||
'\n'
|
'\n'
|
||||||
'To set a default implementation, use:\n'
|
'To set a default implementation, use:\n'
|
||||||
'flutter:\n'
|
'flutter:\n'
|
||||||
' plugin:\n'
|
' plugin:\n'
|
||||||
' platforms:\n'
|
' platforms:\n'
|
||||||
' $platform:\n'
|
' $platformKey:\n'
|
||||||
' $kDefaultPackage: <plugin-implementation>\n'
|
' $kDefaultPackage: <plugin-implementation>\n'
|
||||||
'\n'
|
'\n'
|
||||||
'To implement an interface, use:\n'
|
'To implement an interface, use:\n'
|
||||||
'flutter:\n'
|
'flutter:\n'
|
||||||
' plugin:\n'
|
' plugin:\n'
|
||||||
' implements: <plugin-interface>'
|
' implements: <plugin-interface>'
|
||||||
'\n'
|
'\n',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
hasPubspecError = true;
|
hasPubspecError = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final String defaultImplementationKey = getResolutionKey(platform: platform, packageName: plugin.name);
|
final String defaultImplementationKey = getResolutionKey(platform: platformKey, packageName: plugin.name);
|
||||||
if (defaultImplementation != null) {
|
if (defaultImplementation != null) {
|
||||||
defaultImplementations[defaultImplementationKey] = defaultImplementation;
|
defaultImplementations[defaultImplementationKey] = defaultImplementation;
|
||||||
continue;
|
continue;
|
||||||
@ -1313,7 +1316,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
|||||||
// - the plugin requires at least Flutter 2.11 (when this opt-in logic
|
// - the plugin requires at least Flutter 2.11 (when this opt-in logic
|
||||||
// was added), so that existing plugins continue to work.
|
// was added), so that existing plugins continue to work.
|
||||||
// See https://github.com/flutter/flutter/issues/87862 for details.
|
// 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.VersionConstraint? flutterConstraint = plugin.flutterConstraint;
|
||||||
final semver.Version? minFlutterVersion = flutterConstraint != null &&
|
final semver.Version? minFlutterVersion = flutterConstraint != null &&
|
||||||
flutterConstraint is semver.VersionRange ? flutterConstraint.min : 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 there's no Dart implementation, there's nothing to register.
|
||||||
if (plugin.pluginDartClassPlatforms[platform] == null ||
|
if (plugin.pluginDartClassPlatforms[platformKey] == null ||
|
||||||
plugin.pluginDartClassPlatforms[platform] == 'none') {
|
plugin.pluginDartClassPlatforms[platformKey] == 'none') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it hasn't been skipped, it's a candidate for auto-registration, so
|
// If it hasn't been skipped, it's a candidate for auto-registration, so
|
||||||
// add it as a possible resolution.
|
// add it as a possible resolution.
|
||||||
final String resolutionKey = getResolutionKey(platform: platform, packageName: implementsPackage);
|
final String resolutionKey = getResolutionKey(platform: platformKey, packageName: implementsPackage);
|
||||||
if (!possibleResolutions.containsKey(resolutionKey)) {
|
possibleResolutions.putIfAbsent(resolutionKey, () => <PluginInterfaceResolution>[]);
|
||||||
possibleResolutions[resolutionKey] = <PluginInterfaceResolution>[];
|
|
||||||
}
|
|
||||||
possibleResolutions[resolutionKey]!.add(PluginInterfaceResolution(
|
possibleResolutions[resolutionKey]!.add(PluginInterfaceResolution(
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
platform: platform,
|
platform: platformKey,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasPubspecError && throwOnPluginPubspecError) {
|
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
|
// Now resolve all the possible resolutions to a single option for each
|
||||||
@ -1401,7 +1402,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasResolutionError) {
|
if (hasResolutionError) {
|
||||||
throwToolExit('Please resolve the errors');
|
throwToolExit('Please resolve the plugin implementation selection errors');
|
||||||
}
|
}
|
||||||
return finalResolution;
|
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 {
|
testWithoutContext('selects uncontested implementation from transitive dependency', () async {
|
||||||
final Set<String> directDependencies = <String>{
|
final Set<String> directDependencies = <String>{
|
||||||
'url_launcher_macos',
|
'url_launcher_macos',
|
||||||
@ -538,7 +595,7 @@ void main() {
|
|||||||
|
|
||||||
},
|
},
|
||||||
throwsToolExit(
|
throwsToolExit(
|
||||||
message: 'Please resolve the errors',
|
message: 'Please resolve the plugin implementation selection errors',
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@ -627,7 +684,7 @@ void main() {
|
|||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
throwsToolExit(
|
throwsToolExit(
|
||||||
message: 'Please resolve the errors',
|
message: 'Please resolve the plugin implementation selection errors',
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@ -684,7 +741,7 @@ void main() {
|
|||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
throwsToolExit(
|
throwsToolExit(
|
||||||
message: 'Please resolve the errors',
|
message: 'Please resolve the plugin implementation selection errors',
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
Loading…
Reference in New Issue
Block a user