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
Show 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,10 +174,14 @@ 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
\"
]'
...
...
@@ -193,14 +194,12 @@ public class DummyPluginAClass {
'
\"
name
\"
:
\"
plugin_c
\"
,'
'
\"
dependencies
\"
:[]'
'}'
']'
'}'
;
if
(
flutterPluginsDependenciesFileContent
!=
kExpectedPluginsDependenciesContent
)
{
']'
;
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
File
pluginsFile
=
project
.
flutterPluginsDependenciesFile
;
if
(
plugins
.
isEmpty
)
{
if
(
pluginsFile
.
existsSync
())
{
pluginsFile
.
deleteSync
();
return
true
;
}
return
false
;
}
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
>[];
const
String
info
=
'This is a generated file; do not edit or check into version control.'
;
final
StringBuffer
flutterPluginsBuffer
=
StringBuffer
(
'#
$info
\n
'
);
final
Set
<
String
>
pluginNames
=
<
String
>{}
;
final
Set
<
String
>
pluginNames
=
plugins
.
map
((
Plugin
plugin
)
=>
plugin
.
name
).
toSet
()
;
for
(
final
Plugin
plugin
in
plugins
)
{
pluginNames
.
add
(
plugin
.
name
);
}
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
...
...
@@ -2,13 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:convert'
;
import
'package:file/file.dart'
;
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/base/time.dart'
;
import
'package:flutter_tools/src/dart/package_map.dart'
;
import
'package:flutter_tools/src/features.dart'
;
import
'package:flutter_tools/src/ios/xcodeproj.dart'
;
import
'package:flutter_tools/src/plugins.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:flutter_tools/src/version.dart'
;
import
'package:meta/meta.dart'
;
import
'package:mockito/mockito.dart'
;
...
...
@@ -23,15 +27,22 @@ void main() {
MockMacOSProject
macosProject
;
MockAndroidProject
androidProject
;
MockWebProject
webProject
;
MockWindowsProject
windowsProject
;
MockLinuxProject
linuxProject
;
File
packagesFile
;
Directory
dummyPackageDirectory
;
SystemClock
mockClock
;
FlutterVersion
mockVersion
;
setUp
(()
async
{
fs
=
MemoryFileSystem
();
mockClock
=
MockClock
();
mockVersion
=
MockFlutterVersion
();
// Add basic properties to the Flutter project and subprojects
flutterProject
=
MockFlutterProject
();
when
(
flutterProject
.
directory
).
thenReturn
(
fs
.
directory
(
'/'
));
// TODO(franciscojma): Remove logic for .flutter-plugins it's deprecated.
when
(
flutterProject
.
flutterPluginsFile
).
thenReturn
(
flutterProject
.
directory
.
childFile
(
'.flutter-plugins'
));
when
(
flutterProject
.
flutterPluginsDependenciesFile
).
thenReturn
(
flutterProject
.
directory
.
childFile
(
'.flutter-plugins-dependencies'
));
iosProject
=
MockIosProject
();
...
...
@@ -39,18 +50,41 @@ void main() {
when
(
iosProject
.
pluginRegistrantHost
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'Runner'
));
when
(
iosProject
.
podfile
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'ios'
).
childFile
(
'Podfile'
));
when
(
iosProject
.
podManifestLock
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'ios'
).
childFile
(
'Podfile.lock'
));
when
(
iosProject
.
pluginConfigKey
).
thenReturn
(
'ios'
);
when
(
iosProject
.
existsSync
()).
thenReturn
(
false
);
macosProject
=
MockMacOSProject
();
when
(
flutterProject
.
macos
).
thenReturn
(
macosProject
);
when
(
macosProject
.
podfile
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'macos'
).
childFile
(
'Podfile'
));
when
(
macosProject
.
podManifestLock
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'macos'
).
childFile
(
'Podfile.lock'
));
when
(
macosProject
.
pluginConfigKey
).
thenReturn
(
'macos'
);
when
(
macosProject
.
existsSync
()).
thenReturn
(
false
);
androidProject
=
MockAndroidProject
();
when
(
flutterProject
.
android
).
thenReturn
(
androidProject
);
when
(
androidProject
.
pluginRegistrantHost
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'android'
).
childDirectory
(
'app'
));
when
(
androidProject
.
hostAppGradleRoot
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'android'
));
when
(
androidProject
.
pluginConfigKey
).
thenReturn
(
'android'
);
when
(
androidProject
.
existsSync
()).
thenReturn
(
false
);
webProject
=
MockWebProject
();
when
(
flutterProject
.
web
).
thenReturn
(
webProject
);
when
(
webProject
.
libDirectory
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'lib'
));
when
(
webProject
.
existsSync
()).
thenReturn
(
true
);
when
(
webProject
.
pluginConfigKey
).
thenReturn
(
'web'
);
when
(
webProject
.
existsSync
()).
thenReturn
(
false
);
windowsProject
=
MockWindowsProject
();
when
(
flutterProject
.
windows
).
thenReturn
(
windowsProject
);
when
(
windowsProject
.
pluginConfigKey
).
thenReturn
(
'windows'
);
when
(
windowsProject
.
existsSync
()).
thenReturn
(
false
);
linuxProject
=
MockLinuxProject
();
when
(
flutterProject
.
linux
).
thenReturn
(
linuxProject
);
when
(
linuxProject
.
pluginConfigKey
).
thenReturn
(
'linux'
);
when
(
linuxProject
.
existsSync
()).
thenReturn
(
false
);
when
(
mockClock
.
now
()).
thenAnswer
(
(
Invocation
_
)
=>
DateTime
(
1970
,
1
,
1
)
);
when
(
mockVersion
.
frameworkVersion
).
thenAnswer
(
(
Invocation
_
)
=>
'1.0.0'
);
// Set up a simple .packages file for all the tests to use, pointing to one package.
dummyPackageDirectory
=
fs
.
directory
(
'/pubcache/apackage/lib/'
);
...
...
@@ -67,6 +101,18 @@ void main() {
platforms:
ios:
pluginClass: FLESomePlugin
macos:
pluginClass: FLESomePlugin
windows:
pluginClass: FLESomePlugin
linux:
pluginClass: FLESomePlugin
web:
pluginClass: SomePlugin
fileName: lib/SomeFile.dart
android:
pluginClass: SomePlugin
package: AndroidPackage
'''
);
}
...
...
@@ -239,8 +285,8 @@ dependencies:
testUsingContext
(
'Refreshing the plugin list deletes the plugin file when there were plugins but no longer are'
,
()
{
flutterProject
.
flutterPluginsFile
.
createSync
();
when
(
iosProject
.
existsSync
()).
thenReturn
(
false
);
when
(
macosProject
.
existsSync
()).
thenReturn
(
false
);
flutterProject
.
flutterPluginsDependenciesFile
.
createSync
(
);
refreshPluginsList
(
flutterProject
);
expect
(
flutterProject
.
flutterPluginsFile
.
existsSync
(),
false
);
expect
(
flutterProject
.
flutterPluginsDependenciesFile
.
existsSync
(),
false
);
...
...
@@ -251,8 +297,8 @@ dependencies:
testUsingContext
(
'Refreshing the plugin list creates a plugin directory when there are plugins'
,
()
{
configureDummyPackageAsPlugin
();
when
(
iosProject
.
existsSync
()).
thenReturn
(
fals
e
);
when
(
macosProject
.
existsSync
()).
thenReturn
(
false
);
when
(
iosProject
.
existsSync
()).
thenReturn
(
tru
e
);
refreshPluginsList
(
flutterProject
);
expect
(
flutterProject
.
flutterPluginsFile
.
existsSync
(),
true
);
expect
(
flutterProject
.
flutterPluginsDependenciesFile
.
existsSync
(),
true
);
...
...
@@ -265,11 +311,20 @@ dependencies:
createPluginWithDependencies
(
name:
'plugin-a'
,
dependencies:
const
<
String
>[
'plugin-b'
,
'plugin-c'
,
'random-package'
]);
createPluginWithDependencies
(
name:
'plugin-b'
,
dependencies:
const
<
String
>[
'plugin-c'
]);
createPluginWithDependencies
(
name:
'plugin-c'
,
dependencies:
const
<
String
>[]);
when
(
iosProject
.
existsSync
()).
thenReturn
(
false
);
when
(
macosProject
.
existsSync
()).
thenReturn
(
false
);
when
(
iosProject
.
existsSync
()).
thenReturn
(
true
);
final
DateTime
dateCreated
=
DateTime
(
1970
,
1
,
1
);
when
(
mockClock
.
now
()).
thenAnswer
(
(
Invocation
_
)
=>
dateCreated
);
const
String
version
=
'1.0.0'
;
when
(
mockVersion
.
frameworkVersion
).
thenAnswer
(
(
Invocation
_
)
=>
version
);
refreshPluginsList
(
flutterProject
);
// Verify .flutter-plugins-dependencies is configured correctly.
expect
(
flutterProject
.
flutterPluginsFile
.
existsSync
(),
true
);
expect
(
flutterProject
.
flutterPluginsDependenciesFile
.
existsSync
(),
true
);
expect
(
flutterProject
.
flutterPluginsFile
.
readAsStringSync
(),
...
...
@@ -279,28 +334,79 @@ dependencies:
'plugin-c=/.tmp_rand0/plugin.rand2/
\n
'
''
);
expect
(
flutterProject
.
flutterPluginsDependenciesFile
.
readAsStringSync
(),
'{'
'"_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":["plugin-c"]'
'},'
'{'
'"name":"plugin-c",'
'"dependencies":[]'
'}'
']'
'}'
);
final
String
pluginsString
=
flutterProject
.
flutterPluginsDependenciesFile
.
readAsStringSync
();
final
Map
<
String
,
dynamic
>
jsonContent
=
json
.
decode
(
pluginsString
)
as
Map
<
String
,
dynamic
>;
expect
(
jsonContent
[
'info'
],
'This is a generated file; do not edit or check into version control.'
);
final
Map
<
String
,
dynamic
>
plugins
=
jsonContent
[
'plugins'
]
as
Map
<
String
,
dynamic
>;
final
List
<
dynamic
>
expectedPlugins
=
<
dynamic
>[
<
String
,
dynamic
>
{
'name'
:
'plugin-a'
,
'path'
:
'/.tmp_rand0/plugin.rand0/'
,
'dependencies'
:
<
String
>[
'plugin-b'
,
'plugin-c'
]
},
<
String
,
dynamic
>
{
'name'
:
'plugin-b'
,
'path'
:
'/.tmp_rand0/plugin.rand1/'
,
'dependencies'
:
<
String
>[
'plugin-c'
]
},
<
String
,
dynamic
>
{
'name'
:
'plugin-c'
,
'path'
:
'/.tmp_rand0/plugin.rand2/'
,
'dependencies'
:
<
String
>[]
},
];
expect
(
plugins
[
'ios'
],
expectedPlugins
);
expect
(
plugins
[
'android'
],
expectedPlugins
);
expect
(
plugins
[
'macos'
],
<
dynamic
>[]);
expect
(
plugins
[
'windows'
],
<
dynamic
>[]);
expect
(
plugins
[
'linux'
],
<
dynamic
>[]);
expect
(
plugins
[
'web'
],
<
dynamic
>[]);
final
List
<
dynamic
>
expectedDependencyGraph
=
<
dynamic
>[
<
String
,
dynamic
>
{
'name'
:
'plugin-a'
,
'dependencies'
:
<
String
>[
'plugin-b'
,
'plugin-c'
]
},
<
String
,
dynamic
>
{
'name'
:
'plugin-b'
,
'dependencies'
:
<
String
>[
'plugin-c'
]
},
<
String
,
dynamic
>
{
'name'
:
'plugin-c'
,
'dependencies'
:
<
String
>[]
},
];
expect
(
jsonContent
[
'dependencyGraph'
],
expectedDependencyGraph
);
expect
(
jsonContent
[
'date_created'
],
dateCreated
.
toString
());
expect
(
jsonContent
[
'version'
],
version
);
// Make sure tests are updated if a new object is added/removed.
final
List
<
String
>
expectedKeys
=
<
String
>[
'info'
,
'plugins'
,
'dependencyGraph'
,
'date_created'
,
'version'
,
];
expect
(
jsonContent
.
keys
,
expectedKeys
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
SystemClock:
()
=>
mockClock
,
FlutterVersion:
()
=>
mockVersion
});
testUsingContext
(
'Changes to the plugin list invalidates the Cocoapod lockfiles'
,
()
{
...
...
@@ -315,6 +421,31 @@ dependencies:
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
SystemClock:
()
=>
mockClock
,
FlutterVersion:
()
=>
mockVersion
});
testUsingContext
(
'No changes to the plugin list does not invalidate the Cocoapod lockfiles'
,
()
{
configureDummyPackageAsPlugin
();
when
(
iosProject
.
existsSync
()).
thenReturn
(
true
);
when
(
macosProject
.
existsSync
()).
thenReturn
(
true
);
// First call will create the .flutter-plugins-dependencies and the legacy .flutter-plugins file.
// Since there was no plugins list, the lock files will be invalidated.
// The second call is where the plugins list is compared to the existing one, and if there is no change,
// the podfiles shouldn't be invalidated.
refreshPluginsList
(
flutterProject
);
simulatePodInstallRun
(
iosProject
);
simulatePodInstallRun
(
macosProject
);
refreshPluginsList
(
flutterProject
);
expect
(
iosProject
.
podManifestLock
.
existsSync
(),
true
);
expect
(
macosProject
.
podManifestLock
.
existsSync
(),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
SystemClock:
()
=>
mockClock
,
FlutterVersion:
()
=>
mockVersion
});
});
...
...
@@ -600,6 +731,7 @@ dependencies:
testUsingContext
(
'Registrant for web doesn
\'
t escape slashes in imports'
,
()
async
{
when
(
flutterProject
.
isModule
).
thenReturn
(
true
);
when
(
featureFlags
.
isWebEnabled
).
thenReturn
(
true
);
when
(
webProject
.
existsSync
()).
thenReturn
(
true
);
final
Directory
webPluginWithNestedFile
=
fs
.
systemTempDirectory
.
createTempSync
(
'web_plugin_with_nested'
);
...
...
@@ -648,3 +780,5 @@ class MockIosProject extends Mock implements IosProject {}
class
MockMacOSProject
extends
Mock
implements
MacOSProject
{}
class
MockXcodeProjectInterpreter
extends
Mock
implements
XcodeProjectInterpreter
{}
class
MockWebProject
extends
Mock
implements
WebProject
{}
class
MockWindowsProject
extends
Mock
implements
WindowsProject
{}
class
MockLinuxProject
extends
Mock
implements
LinuxProject
{}
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