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
fcf341e4
Unverified
Commit
fcf341e4
authored
Jan 17, 2020
by
Francisco Magdaleno
Committed by
GitHub
Jan 17, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reland "[flutter_tools] Removes the need of a no-op plugin implementations #48614" (#49085)
parent
2b998405
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
372 additions
and
89 deletions
+372
-89
plugin_dependencies_test.dart
dev/devicelab/bin/tasks/plugin_dependencies_test.dart
+24
-25
plugins.dart
packages/flutter_tools/lib/src/plugins.dart
+148
-33
project.dart
packages/flutter_tools/lib/src/project.dart
+39
-6
version.dart
packages/flutter_tools/lib/src/version.dart
+2
-0
plugins_test.dart
packages/flutter_tools/test/general.shard/plugins_test.dart
+159
-25
No files found.
dev/devicelab/bin/tasks/plugin_dependencies_test.dart
View file @
fcf341e4
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
...
...
@@ -74,10 +75,6 @@ Future<void> main() async {
);
});
// https://github.com/flutter/flutter/issues/46898
// https://github.com/flutter/flutter/issues/39657
File
(
path
.
join
(
pluginCDirectory
.
path
,
'android'
,
'build.gradle'
)).
deleteSync
();
final
File
pluginCpubspec
=
File
(
path
.
join
(
pluginCDirectory
.
path
,
'pubspec.yaml'
));
await
pluginCpubspec
.
writeAsString
(
'''
name: plugin_c
...
...
@@ -177,30 +174,32 @@ public class DummyPluginAClass {
}
final
String
flutterPluginsDependenciesFileContent
=
flutterPluginsDependenciesFile
.
readAsStringSync
();
final
Map
<
String
,
dynamic
>
jsonContent
=
json
.
decode
(
flutterPluginsDependenciesFileContent
)
as
Map
<
String
,
dynamic
>;
// Verify the dependencyGraph object is valid. The rest of the contents of this file are not relevant to the
// dependency graph and are tested by unit tests.
final
List
<
dynamic
>
dependencyGraph
=
jsonContent
[
'dependencyGraph'
]
as
List
<
dynamic
>;
const
String
kExpectedPluginsDependenciesContent
=
'{'
'
\"
_info
\"
:
\"
// This is a generated file; do not edit or check into version control.
\"
,'
'
\"
dependencyGraph
\"
:['
'{'
'
\"
name
\"
:
\"
plugin_a
\"
,'
'
\"
dependencies
\"
:[
\"
plugin_b
\"
,
\"
plugin_c
\"
]'
'},'
'{'
'
\"
name
\"
:
\"
plugin_b
\"
,'
'
\"
dependencies
\"
:[]'
'},'
'{'
'
\"
name
\"
:
\"
plugin_c
\"
,'
'
\"
dependencies
\"
:[]'
'}'
']'
'}'
;
if
(
flutterPluginsDependenciesFileContent
!=
kExpectedPluginsDependenciesContent
)
{
'['
'{'
'
\"
name
\"
:
\"
plugin_a
\"
,'
'
\"
dependencies
\"
:[
\"
plugin_b
\"
,
\"
plugin_c
\"
]'
'},'
'{'
'
\"
name
\"
:
\"
plugin_b
\"
,'
'
\"
dependencies
\"
:[]'
'},'
'{'
'
\"
name
\"
:
\"
plugin_c
\"
,'
'
\"
dependencies
\"
:[]'
'}'
']'
;
final
String
graphString
=
json
.
encode
(
dependencyGraph
);
if
(
graphString
!=
kExpectedPluginsDependenciesContent
)
{
return
TaskResult
.
failure
(
'Unexpected file content in
${flutterPluginsDependenciesFile.path}
: '
'Found "
$flutterPluginsDependenciesFileContent
" instead of '
'"
$kExpectedPluginsDependenciesContent
"'
'Found "
$graphString
" instead of "
$kExpectedPluginsDependenciesContent
"'
);
}
...
...
packages/flutter_tools/lib/src/plugins.dart
View file @
fcf341e4
...
...
@@ -11,6 +11,7 @@ import 'package:yaml/yaml.dart';
import
'android/gradle.dart'
;
import
'base/common.dart'
;
import
'base/file_system.dart'
;
import
'base/time.dart'
;
import
'convert.dart'
;
import
'dart/package_map.dart'
;
import
'features.dart'
;
...
...
@@ -18,6 +19,7 @@ import 'globals.dart' as globals;
import
'macos/cocoapods.dart'
;
import
'platform_plugins.dart'
;
import
'project.dart'
;
import
'version.dart'
;
void
_renderTemplateToFile
(
String
template
,
dynamic
context
,
String
filePath
)
{
final
String
renderedTemplate
=
...
...
@@ -263,7 +265,7 @@ class Plugin {
final
Map
<
String
,
PluginPlatform
>
platforms
;
}
Plugin
_pluginFromP
ubspec
(
String
name
,
Uri
packageRoot
)
{
Plugin
_pluginFromP
ackage
(
String
name
,
Uri
packageRoot
)
{
final
String
pubspecPath
=
globals
.
fs
.
path
.
fromUri
(
packageRoot
.
resolve
(
'pubspec.yaml'
));
if
(!
globals
.
fs
.
isFileSync
(
pubspecPath
))
{
return
null
;
...
...
@@ -302,7 +304,7 @@ List<Plugin> findPlugins(FlutterProject project) {
}
packages
.
forEach
((
String
name
,
Uri
uri
)
{
final
Uri
packageRoot
=
uri
.
resolve
(
'..'
);
final
Plugin
plugin
=
_pluginFromP
ubspec
(
name
,
packageRoot
);
final
Plugin
plugin
=
_pluginFromP
ackage
(
name
,
packageRoot
);
if
(
plugin
!=
null
)
{
plugins
.
add
(
plugin
);
}
...
...
@@ -310,55 +312,163 @@ List<Plugin> findPlugins(FlutterProject project) {
return
plugins
;
}
/// Writes the .flutter-plugins and .flutter-plugins-dependencies files based on the list of plugins.
/// If there aren't any plugins, then the files aren't written to disk.
/// Filters [plugins] to those supported by [platformKey].
List
<
Map
<
String
,
dynamic
>>
_filterPluginsByPlatform
(
List
<
Plugin
>
plugins
,
String
platformKey
)
{
final
Iterable
<
Plugin
>
platformPlugins
=
plugins
.
where
((
Plugin
p
)
{
return
p
.
platforms
.
containsKey
(
platformKey
);
});
final
Set
<
String
>
pluginNames
=
platformPlugins
.
map
((
Plugin
plugin
)
=>
plugin
.
name
).
toSet
();
final
List
<
Map
<
String
,
dynamic
>>
list
=
<
Map
<
String
,
dynamic
>>[];
for
(
final
Plugin
plugin
in
platformPlugins
)
{
list
.
add
(<
String
,
dynamic
>{
'name'
:
plugin
.
name
,
'path'
:
fsUtils
.
escapePath
(
plugin
.
path
),
'dependencies'
:
<
String
>[...
plugin
.
dependencies
.
where
(
pluginNames
.
contains
)],
});
}
return
list
;
}
/// Writes the .flutter-plugins-dependencies file based on the list of plugins.
/// If there aren't any plugins, then the files aren't written to disk. The resulting
/// file looks something like this (order of keys is not guaranteed):
/// {
/// "info": "This is a generated file; do not edit or check into version control.",
/// "plugins": {
/// "ios": [
/// {
/// "name": "test",
/// "path": "test_path",
/// "dependencies": [
/// "plugin-a",
/// "plugin-b"
/// ]
/// }
/// ],
/// "android": [],
/// "macos": [],
/// "linux": [],
/// "windows": [],
/// "web": []
/// },
/// "dependencyGraph": [
/// {
/// "name": "plugin-a",
/// "dependencies": [
/// "plugin-b",
/// "plugin-c"
/// ]
/// },
/// {
/// "name": "plugin-b",
/// "dependencies": [
/// "plugin-c"
/// ]
/// },
/// {
/// "name": "plugin-c",
/// "dependencies": []
/// }
/// ],
/// "date_created": "1970-01-01 00:00:00.000",
/// "version": "0.0.0-unknown"
/// }
///
///
Finally, returns [true] if .flutter-plugins or .flutter-plugins-dependencies have changed,
/// otherwise returns [false].
///
///
Finally, returns [true] if the plugins list has changed,
otherwise returns [false].
bool
_writeFlutterPluginsList
(
FlutterProject
project
,
List
<
Plugin
>
plugins
)
{
final
List
<
dynamic
>
directAppDependencies
=
<
dynamic
>[];
const
String
info
=
'This is a generated file; do not edit or check into version control.'
;
final
StringBuffer
flutterPluginsBuffer
=
StringBuffer
(
'#
$info
\n
'
);
final
File
pluginsFile
=
project
.
flutterPluginsDependenciesFile
;
if
(
plugins
.
isEmpty
)
{
if
(
pluginsFile
.
existsSync
())
{
pluginsFile
.
deleteSync
();
return
true
;
}
return
false
;
}
final
Set
<
String
>
pluginNames
=
<
String
>{};
for
(
final
Plugin
plugin
in
plugins
)
{
pluginNames
.
add
(
plugin
.
name
);
final
String
iosKey
=
project
.
ios
.
pluginConfigKey
;
final
String
androidKey
=
project
.
android
.
pluginConfigKey
;
final
String
macosKey
=
project
.
macos
.
pluginConfigKey
;
final
String
linuxKey
=
project
.
linux
.
pluginConfigKey
;
final
String
windowsKey
=
project
.
windows
.
pluginConfigKey
;
final
String
webKey
=
project
.
web
.
pluginConfigKey
;
final
Map
<
String
,
dynamic
>
pluginsMap
=
<
String
,
dynamic
>{};
pluginsMap
[
iosKey
]
=
_filterPluginsByPlatform
(
plugins
,
iosKey
);
pluginsMap
[
androidKey
]
=
_filterPluginsByPlatform
(
plugins
,
androidKey
);
pluginsMap
[
macosKey
]
=
_filterPluginsByPlatform
(
plugins
,
macosKey
);
pluginsMap
[
linuxKey
]
=
_filterPluginsByPlatform
(
plugins
,
linuxKey
);
pluginsMap
[
windowsKey
]
=
_filterPluginsByPlatform
(
plugins
,
windowsKey
);
pluginsMap
[
webKey
]
=
_filterPluginsByPlatform
(
plugins
,
webKey
);
final
Map
<
String
,
dynamic
>
result
=
<
String
,
dynamic
>
{};
result
[
'info'
]
=
'This is a generated file; do not edit or check into version control.'
;
result
[
'plugins'
]
=
pluginsMap
;
/// The dependencyGraph object is kept for backwards compatibility, but
/// should be removed once migration is complete.
/// https://github.com/flutter/flutter/issues/48918
result
[
'dependencyGraph'
]
=
_createPluginLegacyDependencyGraph
(
plugins
);
result
[
'date_created'
]
=
systemClock
.
now
().
toString
();
result
[
'version'
]
=
flutterVersion
.
frameworkVersion
;
// Only notify if the plugins list has changed. [date_created] will always be different,
// [version] is not relevant for this check.
final
String
oldPluginsFileStringContent
=
_readFileContent
(
pluginsFile
);
bool
pluginsChanged
=
true
;
if
(
oldPluginsFileStringContent
!=
null
)
{
pluginsChanged
=
oldPluginsFileStringContent
.
contains
(
pluginsMap
.
toString
());
}
final
String
pluginFileContent
=
json
.
encode
(
result
);
pluginsFile
.
writeAsStringSync
(
pluginFileContent
,
flush:
true
);
return
pluginsChanged
;
}
List
<
dynamic
>
_createPluginLegacyDependencyGraph
(
List
<
Plugin
>
plugins
)
{
final
List
<
dynamic
>
directAppDependencies
=
<
dynamic
>[];
final
Set
<
String
>
pluginNames
=
plugins
.
map
((
Plugin
plugin
)
=>
plugin
.
name
).
toSet
();
for
(
final
Plugin
plugin
in
plugins
)
{
flutterPluginsBuffer
.
write
(
'
${plugin.name}
=
${fsUtils.escapePath(plugin.path)}
\n
'
);
directAppDependencies
.
add
(<
String
,
dynamic
>{
'name'
:
plugin
.
name
,
// Extract the plugin dependencies which happen to be plugins.
'dependencies'
:
<
String
>[...
plugin
.
dependencies
.
where
(
pluginNames
.
contains
)],
});
}
return
directAppDependencies
;
}
// The .flutter-plugins file will be DEPRECATED in favor of .flutter-plugins-dependencies.
// TODO(franciscojma): Remove this method once deprecated.
// https://github.com/flutter/flutter/issues/48918
//
/// Writes the .flutter-plugins files based on the list of plugins.
/// If there aren't any plugins, then the files aren't written to disk.
///
/// Finally, returns [true] if .flutter-plugins has changed, otherwise returns [false].
bool
_writeFlutterPluginsListLegacy
(
FlutterProject
project
,
List
<
Plugin
>
plugins
)
{
final
File
pluginsFile
=
project
.
flutterPluginsFile
;
final
String
oldPluginFileContent
=
_readFileContent
(
pluginsFile
);
final
String
pluginFileContent
=
flutterPluginsBuffer
.
toString
();
if
(
pluginNames
.
isNotEmpty
)
{
pluginsFile
.
writeAsStringSync
(
pluginFileContent
,
flush:
true
);
}
else
{
if
(
plugins
.
isEmpty
)
{
if
(
pluginsFile
.
existsSync
())
{
pluginsFile
.
deleteSync
();
return
true
;
}
return
false
;
}
final
File
dependenciesFile
=
project
.
flutterPluginsDependenciesFile
;
final
String
oldDependenciesFileContent
=
_readFileContent
(
dependenciesFile
);
final
String
dependenciesFileContent
=
json
.
encode
(<
String
,
dynamic
>{
'_info'
:
'//
$info
'
,
'dependencyGraph'
:
directAppDependencies
,
});
if
(
pluginNames
.
isNotEmpty
)
{
dependenciesFile
.
writeAsStringSync
(
dependenciesFileContent
,
flush:
true
);
}
else
{
if
(
dependenciesFile
.
existsSync
())
{
dependenciesFile
.
deleteSync
();
}
const
String
info
=
'This is a generated file; do not edit or check into version control.'
;
final
StringBuffer
flutterPluginsBuffer
=
StringBuffer
(
'#
$info
\n
'
);
for
(
final
Plugin
plugin
in
plugins
)
{
flutterPluginsBuffer
.
write
(
'
${plugin.name}
=
${fsUtils.escapePath(plugin.path)}
\n
'
);
}
final
String
oldPluginFileContent
=
_readFileContent
(
pluginsFile
);
final
String
pluginFileContent
=
flutterPluginsBuffer
.
toString
();
pluginsFile
.
writeAsStringSync
(
pluginFileContent
,
flush:
true
);
return
oldPluginFileContent
!=
_readFileContent
(
pluginsFile
)
||
oldDependenciesFileContent
!=
_readFileContent
(
dependenciesFile
);
return
oldPluginFileContent
!=
_readFileContent
(
pluginsFile
);
}
/// Returns the contents of [File] or [null] if that file does not exist.
...
...
@@ -782,8 +892,13 @@ Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plug
/// Assumes `pub get` has been executed since last change to `pubspec.yaml`.
void refreshPluginsList(FlutterProject project, {bool checkProjects = false}) {
final List<Plugin> plugins = findPlugins(project);
// TODO(franciscojma): Remove once migration is complete.
// Write the legacy plugin files to avoid breaking existing apps.
final bool legacyChanged = _writeFlutterPluginsListLegacy(project, plugins);
final bool changed = _writeFlutterPluginsList(project, plugins);
if (changed) {
if (changed
|| legacyChanged
) {
if (!checkProjects || project.ios.existsSync()) {
cocoaPods.invalidatePodInstallOutput(project.ios);
}
...
...
packages/flutter_tools/lib/src/project.dart
View file @
fcf341e4
...
...
@@ -20,6 +20,7 @@ import 'flutter_manifest.dart';
import
'globals.dart'
as
globals
;
import
'ios/plist_parser.dart'
;
import
'ios/xcodeproj.dart'
as
xcode
;
import
'platform_plugins.dart'
;
import
'plugins.dart'
;
import
'template.dart'
;
...
...
@@ -251,6 +252,16 @@ class FlutterProject {
}
}
/// Base class for projects per platform.
abstract
class
FlutterProjectPlatform
{
/// Plugin's platform config key, e.g., "macos", "ios".
String
get
pluginConfigKey
;
/// Whether the platform exists in the project.
bool
existsSync
();
}
/// Represents an Xcode-based sub-project.
///
/// This defines interfaces common to iOS and macOS projects.
...
...
@@ -300,12 +311,15 @@ abstract class XcodeBasedProject {
///
/// Instances will reflect the contents of the `ios/` sub-folder of
/// Flutter applications and the `.ios/` sub-folder of Flutter module projects.
class
IosProject
implements
XcodeBasedProject
{
class
IosProject
extends
FlutterProjectPlatform
implements
XcodeBasedProject
{
IosProject
.
fromFlutter
(
this
.
parent
);
@override
final
FlutterProject
parent
;
@override
String
get
pluginConfigKey
=>
IOSPlugin
.
kConfigKey
;
static
final
RegExp
_productBundleIdPattern
=
RegExp
(
r''
'^
\
s*PRODUCT_BUNDLE_IDENTIFIER
\
s*=
\
s*(["'
]?)(.*?)
\
1
;
\
s
*
$
''');
static const String _productBundleIdVariable = r'
$
(
PRODUCT_BUNDLE_IDENTIFIER
)
';
static const String _hostAppBundleName = '
Runner
';
...
...
@@ -574,12 +588,15 @@ class IosProject implements XcodeBasedProject {
///
/// Instances will reflect the contents of the `android/` sub-folder of
/// Flutter applications and the `.android/` sub-folder of Flutter module projects.
class
AndroidProject
{
class
AndroidProject
extends
FlutterProjectPlatform
{
AndroidProject
.
_
(
this
.
parent
);
/// The parent of this project.
final
FlutterProject
parent
;
@override
String
get
pluginConfigKey
=>
AndroidPlugin
.
kConfigKey
;
static
final
RegExp
_applicationIdPattern
=
RegExp
(
'^
\\
s*applicationId
\\
s+[
\'\"
](.*)[
\'\"
]
\\
s*
\$
'
);
static
final
RegExp
_kotlinPluginPattern
=
RegExp
(
'^
\\
s*apply plugin
\
:
\\
s+[
\'\"
]kotlin-android[
\'\"
]
\\
s*
\$
'
);
static
final
RegExp
_groupPattern
=
RegExp
(
'^
\\
s*group
\\
s+[
\'\"
](.*)[
\'\"
]
\\
s*
\$
'
);
...
...
@@ -627,6 +644,7 @@ class AndroidProject {
}
/// Whether the current flutter project has an Android sub-project.
@override
bool
existsSync
()
{
return
parent
.
isModule
||
_editableHostAppDirectory
.
existsSync
();
}
...
...
@@ -760,12 +778,16 @@ enum AndroidEmbeddingVersion {
}
/// Represents the web sub-project of a Flutter project.
class
WebProject
{
class
WebProject
extends
FlutterProjectPlatform
{
WebProject
.
_
(
this
.
parent
);
final
FlutterProject
parent
;
@override
String
get
pluginConfigKey
=>
WebPlugin
.
kConfigKey
;
/// Whether this flutter project has a web sub-project.
@override
bool
existsSync
()
{
return
parent
.
directory
.
childDirectory
(
'web'
).
existsSync
()
&&
indexFile
.
existsSync
();
...
...
@@ -810,12 +832,15 @@ Match _firstMatchInFile(File file, RegExp regExp) {
}
/// The macOS sub project.
class
MacOSProject
implements
XcodeBasedProject
{
class
MacOSProject
extends
FlutterProjectPlatform
implements
XcodeBasedProject
{
MacOSProject
.
_
(
this
.
parent
);
@override
final
FlutterProject
parent
;
@override
String
get
pluginConfigKey
=>
MacOSPlugin
.
kConfigKey
;
static
const
String
_hostAppBundleName
=
'Runner'
;
@override
...
...
@@ -895,11 +920,15 @@ class MacOSProject implements XcodeBasedProject {
}
/// The Windows sub project
class
WindowsProject
{
class
WindowsProject
extends
FlutterProjectPlatform
{
WindowsProject
.
_
(
this
.
project
);
final
FlutterProject
project
;
@override
String
get
pluginConfigKey
=>
WindowsPlugin
.
kConfigKey
;
@override
bool
existsSync
()
=>
_editableDirectory
.
existsSync
();
Directory
get
_editableDirectory
=>
project
.
directory
.
childDirectory
(
'windows'
);
...
...
@@ -933,11 +962,14 @@ class WindowsProject {
}
/// The Linux sub project.
class
LinuxProject
{
class
LinuxProject
extends
FlutterProjectPlatform
{
LinuxProject
.
_
(
this
.
project
);
final
FlutterProject
project
;
@override
String
get
pluginConfigKey
=>
LinuxPlugin
.
kConfigKey
;
Directory
get
_editableDirectory
=>
project
.
directory
.
childDirectory
(
'linux'
);
/// The directory in the project that is managed by Flutter. As much as
...
...
@@ -950,6 +982,7 @@ class LinuxProject {
/// checked in should live here.
Directory
get
ephemeralDirectory
=>
managedDirectory
.
childDirectory
(
'ephemeral'
);
@override
bool
existsSync
()
=>
_editableDirectory
.
existsSync
();
/// The Linux project makefile.
...
...
packages/flutter_tools/lib/src/version.dart
View file @
fcf341e4
...
...
@@ -16,6 +16,8 @@ import 'cache.dart';
import
'convert.dart'
;
import
'globals.dart'
as
globals
;
FlutterVersion
get
flutterVersion
=>
context
.
get
<
FlutterVersion
>();
class
FlutterVersion
{
FlutterVersion
([
this
.
_clock
=
const
SystemClock
()])
{
_frameworkRevision
=
_runGit
(
gitLog
(<
String
>[
'-n'
,
'1'
,
'--pretty=format:%H'
]).
join
(
' '
));
...
...
packages/flutter_tools/test/general.shard/plugins_test.dart
View file @
fcf341e4
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