Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
62116f99
Unverified
Commit
62116f99
authored
Mar 09, 2023
by
stuartmorgan
Committed by
GitHub
Mar 09, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve Dart plugin registration handling (#122046)
Improve Dart plugin registration handling
parent
7e000b29
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
248 additions
and
113 deletions
+248
-113
flutter_plugins.dart
packages/flutter_tools/lib/src/flutter_plugins.dart
+80
-40
plugins.dart
packages/flutter_tools/lib/src/plugins.dart
+5
-0
dart_plugin_test.dart
...es/flutter_tools/test/general.shard/dart_plugin_test.dart
+163
-73
No files found.
packages/flutter_tools/lib/src/flutter_plugins.dart
View file @
62116f99
...
...
@@ -1191,13 +1191,13 @@ bool hasPlugins(FlutterProject project) {
/// Resolves the platform implementation for Dart-only plugins.
///
/// * If there
are multiple direct pub dependencies on packages that implement
the
/// frontend plugin for the current platform,
fail
.
/// * If there
is only one dependency on a package that implements
the
/// frontend plugin for the current platform,
use that
.
/// * If there is a single direct dependency on a package that implements the
/// frontend plugin for the
target platform, this package is the selected implementation
.
/// * If there is no direct dependency on a package that implements the
frontend
///
plugin for the target platform, and the frontend plugin has a default implementation
///
for the target platform the default implementation is selected
.
/// frontend plugin for the
current platform, use that
.
/// * If there is no direct dependency on a package that implements the
///
frontend plugin, but there is a default for the current platform,
///
use that
.
/// * Else fail.
///
/// For more details, https://flutter.dev/go/federated-plugins.
...
...
@@ -1214,11 +1214,15 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
MacOSPlugin
.
kConfigKey
,
WindowsPlugin
.
kConfigKey
,
];
final
Map
<
String
,
PluginInterfaceResolution
>
directDependency
Resolutions
=
<
String
,
PluginInterfaceResolution
>{};
final
Map
<
String
,
List
<
PluginInterfaceResolution
>>
possible
Resolutions
=
<
String
,
List
<
PluginInterfaceResolution
>
>{};
final
Map
<
String
,
String
>
defaultImplementations
=
<
String
,
String
>{};
bool
didFindError
=
false
;
// Generates a key for the maps above.
String
getResolutionKey
({
required
String
platform
,
required
String
packageName
})
{
return
'
$packageName
:
$platform
'
;
}
bool
hasPubspecError
=
false
;
for
(
final
Plugin
plugin
in
plugins
)
{
for
(
final
String
platform
in
platforms
)
{
if
(
plugin
.
platforms
[
platform
]
==
null
&&
...
...
@@ -1257,11 +1261,12 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
'
\n
'
);
}
didFind
Error
=
true
;
hasPubspec
Error
=
true
;
continue
;
}
final
String
defaultImplementationKey
=
getResolutionKey
(
platform:
platform
,
packageName:
plugin
.
name
);
if
(
defaultImplementation
!=
null
)
{
defaultImplementations
[
'
$platform
/
${plugin.name}
'
]
=
defaultImplementation
;
defaultImplementations
[
defaultImplementationKey
]
=
defaultImplementation
;
continue
;
}
else
{
// An app-facing package (i.e., one with no 'implements') with an
...
...
@@ -1281,52 +1286,87 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
minFlutterVersion
.
compareTo
(
semver
.
Version
(
2
,
11
,
0
))
>=
0
;
if
(!
isDesktop
||
hasMinVersionForImplementsRequirement
)
{
implementsPackage
=
plugin
.
name
;
defaultImplementations
[
'
$platform
/
${plugin.name}
'
]
=
plugin
.
name
;
defaultImplementations
[
defaultImplementationKey
]
=
plugin
.
name
;
}
else
{
// If it doesn't meet any of the conditions, it isn't eligible for
// auto-registration.
continue
;
}
}
}
// If there's no Dart implementation, there's nothing to register.
if
(
plugin
.
pluginDartClassPlatforms
[
platform
]
==
null
||
plugin
.
pluginDartClassPlatforms
[
platform
]
==
'none'
)
{
continue
;
}
final
String
resolutionKey
=
'
$platform
/
$implementsPackage
'
;
if
(
directDependencyResolutions
.
containsKey
(
resolutionKey
))
{
final
PluginInterfaceResolution
?
currResolution
=
directDependencyResolutions
[
resolutionKey
];
if
(
currResolution
!=
null
&&
currResolution
.
plugin
.
isDirectDependency
)
{
if
(
plugin
.
isDirectDependency
)
{
if
(
throwOnPluginPubspecError
)
{
globals
.
printError
(
'Plugin `
${plugin.name}
` implements an interface for `
$platform
`, which was already '
'implemented by plugin `
${currResolution.plugin.name}
`.
\n
'
'To fix this issue, remove either dependency from pubspec.yaml.'
'
\n\n
'
);
}
didFindError
=
true
;
}
// Use the plugin implementation added by the user as a direct dependency.
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
>[];
}
directDependencyResolutions
[
resolutionKey
]
=
PluginInterfaceResolution
(
possibleResolutions
[
resolutionKey
]!.
add
(
PluginInterfaceResolution
(
plugin:
plugin
,
platform:
platform
,
);
)
)
;
}
}
if
(
didFind
Error
&&
throwOnPluginPubspecError
)
{
if
(
hasPubspec
Error
&&
throwOnPluginPubspecError
)
{
throwToolExit
(
'Please resolve the errors'
);
}
// Now resolve all the possible resolutions to a single option for each
// plugin, or throw if that's not possible.
bool
hasResolutionError
=
false
;
final
List
<
PluginInterfaceResolution
>
finalResolution
=
<
PluginInterfaceResolution
>[];
for
(
final
MapEntry
<
String
,
PluginInterfaceResolution
>
resolution
in
directDependencyResolutions
.
entries
)
{
if
(
resolution
.
value
.
plugin
.
isDirectDependency
)
{
finalResolution
.
add
(
resolution
.
value
);
}
else
if
(
defaultImplementations
.
containsKey
(
resolution
.
key
))
{
// Pick the default implementation.
if
(
defaultImplementations
[
resolution
.
key
]
==
resolution
.
value
.
plugin
.
name
)
{
finalResolution
.
add
(
resolution
.
value
);
for
(
final
MapEntry
<
String
,
List
<
PluginInterfaceResolution
>>
entry
in
possibleResolutions
.
entries
)
{
final
List
<
PluginInterfaceResolution
>
candidates
=
entry
.
value
;
// If there's only one candidate, use it.
if
(
candidates
.
length
==
1
)
{
finalResolution
.
add
(
candidates
.
first
);
continue
;
}
// Next, try direct dependencies of the resolving application.
final
Iterable
<
PluginInterfaceResolution
>
directDependencies
=
candidates
.
where
((
PluginInterfaceResolution
r
)
{
return
r
.
plugin
.
isDirectDependency
;
});
if
(
directDependencies
.
isNotEmpty
)
{
if
(
directDependencies
.
length
>
1
)
{
globals
.
printError
(
'Plugin
${entry.key}
has conflicting direct dependency implementations:
\n
'
'
${directDependencies.map((PluginInterfaceResolution r) => ' ${r.plugin.name}
\n
'
).
join
()}
'
'
To
fix
this
issue
,
remove
all
but
one
of
these
dependencies
from
pubspec
.
yaml
.
\
n
'
);
hasResolutionError = true;
} else {
finalResolution.add(directDependencies.first);
}
continue;
}
// Next, defer to the default implementation if there is one.
final String? defaultPackageName = defaultImplementations[entry.key];
if (defaultPackageName != null) {
final int defaultIndex = candidates
.indexWhere((PluginInterfaceResolution r) => r.plugin.name == defaultPackageName);
if (defaultIndex != -1) {
finalResolution.add(candidates[defaultIndex]);
continue;
}
}
// Otherwise, require an explicit choice.
if (candidates.length > 1) {
globals.printError(
'
Plugin
$
{
entry
.
key
}
has
multiple
possible
implementations:
\
n
'
'
$
{
candidates
.
map
((
PluginInterfaceResolution
r
)
=>
'
${r.plugin.name}
\n
'
).
join
()}
'
'
To
fix
this
issue
,
add
one
of
these
dependencies
to
pubspec
.
yaml
.
\
n
'
);
hasResolutionError = true;
continue;
}
}
if (hasResolutionError) {
throwToolExit('
Please
resolve
the
errors
');
}
return finalResolution;
}
...
...
packages/flutter_tools/lib/src/plugins.dart
View file @
62116f99
...
...
@@ -418,4 +418,9 @@ class PluginInterfaceResolution {
'dartClass'
:
plugin
.
pluginDartClassPlatforms
[
platform
]
??
''
,
};
}
@override
String
toString
()
{
return
'<PluginInterfaceResolution
${plugin.name}
for
$platform
>'
;
}
}
packages/flutter_tools/test/general.shard/dart_plugin_test.dart
View file @
62116f99
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment