mirror of
https://github.com/flutter/flutter
synced 2024-10-12 19:23:02 +00:00
migrate vm service to null safety (#88320)
This commit is contained in:
parent
0e78416737
commit
91dd3276fd
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
|
@ -48,12 +46,12 @@ const List<Map<String, Object>> kMaterialFonts = <Map<String, Object>>[
|
|||
/// Injected factory class for spawning [AssetBundle] instances.
|
||||
abstract class AssetBundleFactory {
|
||||
/// The singleton instance, pulled from the [AppContext].
|
||||
static AssetBundleFactory get instance => context.get<AssetBundleFactory>();
|
||||
static AssetBundleFactory get instance => context.get<AssetBundleFactory>()!;
|
||||
|
||||
static AssetBundleFactory defaultInstance({
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
@required Platform platform,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
required Platform platform,
|
||||
bool splitDeferredAssets = false,
|
||||
}) => _ManifestAssetBundleFactory(logger: logger, fileSystem: fileSystem, platform: platform, splitDeferredAssets: splitDeferredAssets);
|
||||
|
||||
|
@ -82,18 +80,18 @@ abstract class AssetBundle {
|
|||
/// Returns 0 for success; non-zero for failure.
|
||||
Future<int> build({
|
||||
String manifestPath = defaultManifestPath,
|
||||
String assetDirPath,
|
||||
@required String packagesPath,
|
||||
String? assetDirPath,
|
||||
required String packagesPath,
|
||||
bool deferredComponentsEnabled = false,
|
||||
TargetPlatform targetPlatform,
|
||||
TargetPlatform? targetPlatform,
|
||||
});
|
||||
}
|
||||
|
||||
class _ManifestAssetBundleFactory implements AssetBundleFactory {
|
||||
_ManifestAssetBundleFactory({
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
@required Platform platform,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
required Platform platform,
|
||||
bool splitDeferredAssets = false,
|
||||
}) : _logger = logger,
|
||||
_fileSystem = fileSystem,
|
||||
|
@ -114,9 +112,9 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
/// Constructs an [ManifestAssetBundle] that gathers the set of assets from the
|
||||
/// pubspec.yaml manifest.
|
||||
ManifestAssetBundle({
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
@required Platform platform,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
required Platform platform,
|
||||
bool splitDeferredAssets = false,
|
||||
}) : _logger = logger,
|
||||
_fileSystem = fileSystem,
|
||||
|
@ -144,7 +142,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
// the current project.
|
||||
final Map<Uri, Directory> _wildcardDirectories = <Uri, Directory>{};
|
||||
|
||||
DateTime _lastBuildTimestamp;
|
||||
DateTime? _lastBuildTimestamp;
|
||||
|
||||
static const String _kAssetManifestJson = 'AssetManifest.json';
|
||||
static const String _kNoticeFile = 'NOTICES';
|
||||
|
@ -161,7 +159,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
|
||||
@override
|
||||
bool needsBuild({ String manifestPath = defaultManifestPath }) {
|
||||
final DateTime lastBuildTimestamp = _lastBuildTimestamp;
|
||||
final DateTime? lastBuildTimestamp = _lastBuildTimestamp;
|
||||
if (lastBuildTimestamp == null) {
|
||||
return true;
|
||||
}
|
||||
|
@ -192,10 +190,10 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
@override
|
||||
Future<int> build({
|
||||
String manifestPath = defaultManifestPath,
|
||||
String assetDirPath,
|
||||
@required String packagesPath,
|
||||
String? assetDirPath,
|
||||
required String packagesPath,
|
||||
bool deferredComponentsEnabled = false,
|
||||
TargetPlatform targetPlatform,
|
||||
TargetPlatform? targetPlatform,
|
||||
}) async {
|
||||
assetDirPath ??= getAssetBuildDirectory();
|
||||
FlutterProject flutterProject;
|
||||
|
@ -244,7 +242,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
if (flutterProject.linux.existsSync())
|
||||
flutterProject.linux.managedDirectory.path,
|
||||
];
|
||||
final Map<_Asset, List<_Asset>> assetVariants = _parseAssets(
|
||||
final Map<_Asset, List<_Asset>>? assetVariants = _parseAssets(
|
||||
packageConfig,
|
||||
flutterManifest,
|
||||
wildcardDirectories,
|
||||
|
@ -274,7 +272,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
}
|
||||
|
||||
final bool includesMaterialFonts = flutterManifest.usesMaterialDesign;
|
||||
final List<Map<String, dynamic>> fonts = _parseFonts(
|
||||
final List<Map<String, Object?>> fonts = _parseFonts(
|
||||
flutterManifest,
|
||||
packageConfig,
|
||||
primary: true,
|
||||
|
@ -287,7 +285,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
if (packageUri != null && packageUri.scheme == 'file') {
|
||||
final String packageManifestPath = _fileSystem.path.fromUri(packageUri.resolve('../pubspec.yaml'));
|
||||
inputFiles.add(_fileSystem.file(packageManifestPath));
|
||||
final FlutterManifest packageFlutterManifest = FlutterManifest.createFromPath(
|
||||
final FlutterManifest? packageFlutterManifest = FlutterManifest.createFromPath(
|
||||
packageManifestPath,
|
||||
logger: _logger,
|
||||
fileSystem: _fileSystem,
|
||||
|
@ -309,7 +307,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
}
|
||||
final String packageBasePath = _fileSystem.path.dirname(packageManifestPath);
|
||||
|
||||
final Map<_Asset, List<_Asset>> packageAssets = _parseAssets(
|
||||
final Map<_Asset, List<_Asset>>? packageAssets = _parseAssets(
|
||||
packageConfig,
|
||||
packageFlutterManifest,
|
||||
// Do not track wildcard directories for dependencies.
|
||||
|
@ -344,11 +342,12 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
// asset in entries.
|
||||
for (final _Asset asset in assetVariants.keys) {
|
||||
final File assetFile = asset.lookupAssetFile(_fileSystem);
|
||||
if (!assetFile.existsSync() && assetVariants[asset].isEmpty) {
|
||||
final List<_Asset> variants = assetVariants[asset]!;
|
||||
if (!assetFile.existsSync() && variants.isEmpty) {
|
||||
_logger.printStatus('Error detected in pubspec.yaml:', emphasis: true);
|
||||
_logger.printError('No file or variants found for $asset.\n');
|
||||
if (asset.package != null) {
|
||||
_logger.printError('This asset was included from package ${asset.package.name}.');
|
||||
_logger.printError('This asset was included from package ${asset.package?.name}.');
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -359,10 +358,10 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
// "1x" resolution variant and if both exist then the explicit 1x
|
||||
// variant is preferred.
|
||||
if (assetFile.existsSync()) {
|
||||
assert(!assetVariants[asset].contains(asset));
|
||||
assetVariants[asset].insert(0, asset);
|
||||
assert(!variants.contains(asset));
|
||||
variants.insert(0, asset);
|
||||
}
|
||||
for (final _Asset variant in assetVariants[asset]) {
|
||||
for (final _Asset variant in variants) {
|
||||
final File variantFile = variant.lookupAssetFile(_fileSystem);
|
||||
inputFiles.add(variantFile);
|
||||
assert(variantFile.existsSync());
|
||||
|
@ -374,13 +373,14 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
if (deferredComponentsAssetVariants != null) {
|
||||
for (final String componentName in deferredComponentsAssetVariants.keys) {
|
||||
deferredComponentsEntries[componentName] = <String, DevFSContent>{};
|
||||
for (final _Asset asset in deferredComponentsAssetVariants[componentName].keys) {
|
||||
final Map<_Asset, List<_Asset>> assetsMap = deferredComponentsAssetVariants[componentName]!;
|
||||
for (final _Asset asset in assetsMap.keys) {
|
||||
final File assetFile = asset.lookupAssetFile(_fileSystem);
|
||||
if (!assetFile.existsSync() && deferredComponentsAssetVariants[componentName][asset].isEmpty) {
|
||||
if (!assetFile.existsSync() && assetsMap[asset]!.isEmpty) {
|
||||
_logger.printStatus('Error detected in pubspec.yaml:', emphasis: true);
|
||||
_logger.printError('No file or variants found for $asset.\n');
|
||||
if (asset.package != null) {
|
||||
_logger.printError('This asset was included from package ${asset.package.name}.');
|
||||
_logger.printError('This asset was included from package ${asset.package?.name}.');
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -391,13 +391,13 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
// "1x" resolution variant and if both exist then the explicit 1x
|
||||
// variant is preferred.
|
||||
if (assetFile.existsSync()) {
|
||||
assert(!deferredComponentsAssetVariants[componentName][asset].contains(asset));
|
||||
deferredComponentsAssetVariants[componentName][asset].insert(0, asset);
|
||||
assert(!assetsMap[asset]!.contains(asset));
|
||||
assetsMap[asset]!.insert(0, asset);
|
||||
}
|
||||
for (final _Asset variant in deferredComponentsAssetVariants[componentName][asset]) {
|
||||
for (final _Asset variant in assetsMap[asset]!) {
|
||||
final File variantFile = variant.lookupAssetFile(_fileSystem);
|
||||
assert(variantFile.existsSync());
|
||||
deferredComponentsEntries[componentName][variant.entryUri.path] ??= DevFSFileContent(variantFile);
|
||||
deferredComponentsEntries[componentName]![variant.entryUri.path] ??= DevFSFileContent(variantFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
entries[key] = content;
|
||||
return;
|
||||
}
|
||||
final DevFSStringContent oldContent = entries[key] as DevFSStringContent;
|
||||
final DevFSStringContent? oldContent = entries[key] as DevFSStringContent?;
|
||||
if (oldContent?.string != content.string) {
|
||||
entries[key] = content;
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
|
||||
void _setLicenseIfChanged(
|
||||
String combinedLicenses,
|
||||
TargetPlatform targetPlatform,
|
||||
TargetPlatform? targetPlatform,
|
||||
) {
|
||||
// On the web, don't compress the NOTICES file since the client doesn't have
|
||||
// dart:io to decompress it. So use the standard _setIfChanged to check if
|
||||
|
@ -478,7 +478,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
// the uncompressed strings to not incur decompression/decoding while making
|
||||
// the comparison.
|
||||
if (!entries.containsKey(_kNoticeZippedFile) ||
|
||||
(entries[_kNoticeZippedFile] as DevFSStringCompressingBytesContent)
|
||||
(entries[_kNoticeZippedFile] as DevFSStringCompressingBytesContent?)
|
||||
?.equals(combinedLicenses) != true) {
|
||||
entries[_kNoticeZippedFile] = DevFSStringCompressingBytesContent(
|
||||
combinedLicenses,
|
||||
|
@ -493,18 +493,18 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
List<_Asset> _getMaterialAssets() {
|
||||
final List<_Asset> result = <_Asset>[];
|
||||
for (final Map<String, Object> family in kMaterialFonts) {
|
||||
final Object fonts = family['fonts'];
|
||||
final Object? fonts = family['fonts'];
|
||||
if (fonts == null) {
|
||||
continue;
|
||||
}
|
||||
for (final Map<String, Object> font in fonts as List<Map<String, String>>) {
|
||||
final String asset = font['asset'] as String;
|
||||
final String? asset = font['asset'] as String?;
|
||||
if (asset == null) {
|
||||
continue;
|
||||
}
|
||||
final Uri entryUri = _fileSystem.path.toUri(asset);
|
||||
result.add(_Asset(
|
||||
baseDir: _fileSystem.path.join(Cache.flutterRoot, 'bin', 'cache', 'artifacts', 'material_fonts'),
|
||||
baseDir: _fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'artifacts', 'material_fonts'),
|
||||
relativeUri: Uri(path: entryUri.pathSegments.last),
|
||||
entryUri: entryUri,
|
||||
package: null,
|
||||
|
@ -515,13 +515,13 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
return result;
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> _parseFonts(
|
||||
List<Map<String, Object?>> _parseFonts(
|
||||
FlutterManifest manifest,
|
||||
PackageConfig packageConfig, {
|
||||
String packageName,
|
||||
@required bool primary,
|
||||
String? packageName,
|
||||
required bool primary,
|
||||
}) {
|
||||
return <Map<String, dynamic>>[
|
||||
return <Map<String, Object?>>[
|
||||
if (primary && manifest.usesMaterialDesign)
|
||||
...kMaterialFonts,
|
||||
if (packageName == null)
|
||||
|
@ -543,7 +543,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
Directory projectDirectory, {
|
||||
List<String> excludeDirs = const <String>[],
|
||||
}) {
|
||||
final List<DeferredComponent> components = flutterManifest.deferredComponents;
|
||||
final List<DeferredComponent>? components = flutterManifest.deferredComponents;
|
||||
final Map<String, Map<_Asset, List<_Asset>>> deferredComponentsAssetVariants = <String, Map<_Asset, List<_Asset>>>{};
|
||||
if (components == null) {
|
||||
return deferredComponentsAssetVariants;
|
||||
|
@ -559,7 +559,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
flutterManifest,
|
||||
assetBasePath,
|
||||
cache,
|
||||
deferredComponentsAssetVariants[component.name],
|
||||
deferredComponentsAssetVariants[component.name]!,
|
||||
assetUri,
|
||||
excludeDirs: excludeDirs,
|
||||
);
|
||||
|
@ -569,7 +569,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
flutterManifest,
|
||||
assetBasePath,
|
||||
cache,
|
||||
deferredComponentsAssetVariants[component.name],
|
||||
deferredComponentsAssetVariants[component.name]!,
|
||||
assetUri,
|
||||
excludeDirs: excludeDirs,
|
||||
);
|
||||
|
@ -604,7 +604,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
final List<_Asset> sortedKeys = jsonEntries.keys.toList()
|
||||
..sort((_Asset left, _Asset right) => left.entryUri.path.compareTo(right.entryUri.path));
|
||||
for (final _Asset main in sortedKeys) {
|
||||
jsonObject[main.entryUri.path] = jsonEntries[main];
|
||||
jsonObject[main.entryUri.path] = jsonEntries[main]!;
|
||||
}
|
||||
return DevFSStringContent(json.encode(jsonObject));
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
final Uri assetUri = fontAsset.assetUri;
|
||||
if (assetUri.pathSegments.first == 'packages' &&
|
||||
!_fileSystem.isFileSync(_fileSystem.path.fromUri(
|
||||
packageConfig[packageName]?.packageUriRoot?.resolve('../${assetUri.path}')))) {
|
||||
packageConfig[packageName]?.packageUriRoot.resolve('../${assetUri.path}')))) {
|
||||
packageFontAssets.add(FontAsset(
|
||||
fontAsset.assetUri,
|
||||
weight: fontAsset.weight,
|
||||
|
@ -667,14 +667,14 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
/// ],
|
||||
/// }
|
||||
/// ```
|
||||
Map<_Asset, List<_Asset>> _parseAssets(
|
||||
Map<_Asset, List<_Asset>>? _parseAssets(
|
||||
PackageConfig packageConfig,
|
||||
FlutterManifest flutterManifest,
|
||||
List<Uri> wildcardDirectories,
|
||||
String assetBase, {
|
||||
List<String> excludeDirs = const <String>[],
|
||||
String packageName,
|
||||
Package attributedPackage,
|
||||
String? packageName,
|
||||
Package? attributedPackage,
|
||||
}) {
|
||||
final Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{};
|
||||
|
||||
|
@ -737,8 +737,8 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
Map<_Asset, List<_Asset>> result,
|
||||
Uri assetUri, {
|
||||
List<String> excludeDirs = const <String>[],
|
||||
String packageName,
|
||||
Package attributedPackage,
|
||||
String? packageName,
|
||||
Package? attributedPackage,
|
||||
}) {
|
||||
final String directoryPath = _fileSystem.path.join(
|
||||
assetBase, assetUri.toFilePath(windows: _platform.isWindows));
|
||||
|
@ -777,8 +777,8 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
Map<_Asset, List<_Asset>> result,
|
||||
Uri assetUri, {
|
||||
List<String> excludeDirs = const <String>[],
|
||||
String packageName,
|
||||
Package attributedPackage,
|
||||
String? packageName,
|
||||
Package? attributedPackage,
|
||||
}) {
|
||||
final _Asset asset = _resolveAsset(
|
||||
packageConfig,
|
||||
|
@ -792,7 +792,7 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
for (final String path in cache.variantsFor(assetFile.path)) {
|
||||
final String relativePath = _fileSystem.path.relative(path, from: asset.baseDir);
|
||||
final Uri relativeUri = _fileSystem.path.toUri(relativePath);
|
||||
final Uri entryUri = asset.symbolicPrefixUri == null
|
||||
final Uri? entryUri = asset.symbolicPrefixUri == null
|
||||
? relativeUri
|
||||
: asset.symbolicPrefixUri?.resolveUri(relativeUri);
|
||||
if (entryUri != null) {
|
||||
|
@ -814,15 +814,15 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
PackageConfig packageConfig,
|
||||
String assetsBaseDir,
|
||||
Uri assetUri,
|
||||
String packageName,
|
||||
Package attributedPackage,
|
||||
String? packageName,
|
||||
Package? attributedPackage,
|
||||
) {
|
||||
final String assetPath = _fileSystem.path.fromUri(assetUri);
|
||||
if (assetUri.pathSegments.first == 'packages'
|
||||
&& !_fileSystem.isFileSync(_fileSystem.path.join(assetsBaseDir, assetPath))) {
|
||||
// The asset is referenced in the pubspec.yaml as
|
||||
// 'packages/PACKAGE_NAME/PATH/TO/ASSET .
|
||||
final _Asset packageAsset = _resolvePackageAsset(
|
||||
final _Asset? packageAsset = _resolvePackageAsset(
|
||||
assetUri,
|
||||
packageConfig,
|
||||
attributedPackage,
|
||||
|
@ -842,12 +842,12 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
);
|
||||
}
|
||||
|
||||
_Asset _resolvePackageAsset(Uri assetUri, PackageConfig packageConfig, Package attributedPackage) {
|
||||
_Asset? _resolvePackageAsset(Uri assetUri, PackageConfig packageConfig, Package? attributedPackage) {
|
||||
assert(assetUri.pathSegments.first == 'packages');
|
||||
if (assetUri.pathSegments.length > 1) {
|
||||
final String packageName = assetUri.pathSegments[1];
|
||||
final Package package = packageConfig[packageName];
|
||||
final Uri packageUri = package?.packageUriRoot;
|
||||
final Package? package = packageConfig[packageName];
|
||||
final Uri? packageUri = package?.packageUriRoot;
|
||||
if (packageUri != null && packageUri.scheme == 'file') {
|
||||
return _Asset(
|
||||
baseDir: _fileSystem.path.fromUri(packageUri),
|
||||
|
@ -869,15 +869,15 @@ class ManifestAssetBundle implements AssetBundle {
|
|||
@immutable
|
||||
class _Asset {
|
||||
const _Asset({
|
||||
@required this.baseDir,
|
||||
@required this.relativeUri,
|
||||
@required this.entryUri,
|
||||
@required this.package,
|
||||
required this.baseDir,
|
||||
required this.relativeUri,
|
||||
required this.entryUri,
|
||||
required this.package,
|
||||
});
|
||||
|
||||
final String baseDir;
|
||||
|
||||
final Package package;
|
||||
final Package? package;
|
||||
|
||||
/// A platform-independent URL where this asset can be found on disk on the
|
||||
/// host system relative to [baseDir].
|
||||
|
@ -892,7 +892,7 @@ class _Asset {
|
|||
|
||||
/// The delta between what the entryUri is and the relativeUri (e.g.,
|
||||
/// packages/flutter_gallery).
|
||||
Uri get symbolicPrefixUri {
|
||||
Uri? get symbolicPrefixUri {
|
||||
if (entryUri == relativeUri) {
|
||||
return null;
|
||||
}
|
||||
|
@ -966,11 +966,11 @@ class _AssetDirectoryCache {
|
|||
continue;
|
||||
}
|
||||
variants[variantName] ??= <String>[];
|
||||
variants[variantName].add(path);
|
||||
variants[variantName]!.add(path);
|
||||
}
|
||||
_cache[directory] = variants;
|
||||
}
|
||||
|
||||
return _cache[directory][assetName] ?? const <String>[];
|
||||
return _cache[directory]![assetName] ?? const <String>[];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -471,8 +471,8 @@ abstract class ResidentCompiler {
|
|||
List<Uri>? invalidatedFiles, {
|
||||
required String outputPath,
|
||||
required PackageConfig packageConfig,
|
||||
required String projectRootPath,
|
||||
required FileSystem fs,
|
||||
String? projectRootPath,
|
||||
bool suppressErrors = false,
|
||||
bool checkDartPluginRegistry = false,
|
||||
});
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
|
@ -29,7 +26,7 @@ class DevFSConfig {
|
|||
bool noDirectorySymlinks = false;
|
||||
}
|
||||
|
||||
DevFSConfig get devFSConfig => context.get<DevFSConfig>();
|
||||
DevFSConfig? get devFSConfig => context.get<DevFSConfig>();
|
||||
|
||||
/// Common superclass for content copied to the device.
|
||||
abstract class DevFSContent {
|
||||
|
@ -60,11 +57,11 @@ class DevFSFileContent extends DevFSContent {
|
|||
DevFSFileContent(this.file);
|
||||
|
||||
final FileSystemEntity file;
|
||||
File _linkTarget;
|
||||
FileStat _fileStat;
|
||||
File? _linkTarget;
|
||||
FileStat? _fileStat;
|
||||
|
||||
File _getFile() {
|
||||
final File linkTarget = _linkTarget;
|
||||
final File? linkTarget = _linkTarget;
|
||||
if (linkTarget != null) {
|
||||
return linkTarget;
|
||||
}
|
||||
|
@ -76,7 +73,7 @@ class DevFSFileContent extends DevFSContent {
|
|||
}
|
||||
|
||||
void _stat() {
|
||||
final File linkTarget = _linkTarget;
|
||||
final File? linkTarget = _linkTarget;
|
||||
if (linkTarget != null) {
|
||||
// Stat the cached symlink target.
|
||||
final FileStat fileStat = linkTarget.statSync();
|
||||
|
@ -106,9 +103,9 @@ class DevFSFileContent extends DevFSContent {
|
|||
|
||||
@override
|
||||
bool get isModified {
|
||||
final FileStat oldFileStat = _fileStat;
|
||||
final FileStat? oldFileStat = _fileStat;
|
||||
_stat();
|
||||
final FileStat newFileStat = _fileStat;
|
||||
final FileStat? newFileStat = _fileStat;
|
||||
if (oldFileStat == null && newFileStat == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -117,9 +114,9 @@ class DevFSFileContent extends DevFSContent {
|
|||
|
||||
@override
|
||||
bool isModifiedAfter(DateTime time) {
|
||||
final FileStat oldFileStat = _fileStat;
|
||||
final FileStat? oldFileStat = _fileStat;
|
||||
_stat();
|
||||
final FileStat newFileStat = _fileStat;
|
||||
final FileStat? newFileStat = _fileStat;
|
||||
if (oldFileStat == null && newFileStat == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -218,7 +215,7 @@ class DevFSStringContent extends DevFSByteContent {
|
|||
/// The `hintString` parameter is a zlib dictionary hinting mechanism to suggest
|
||||
/// the most common string occurrences to potentially assist with compression.
|
||||
class DevFSStringCompressingBytesContent extends DevFSContent {
|
||||
DevFSStringCompressingBytesContent(this._string, { String hintString })
|
||||
DevFSStringCompressingBytesContent(this._string, { String? hintString })
|
||||
: _compressor = ZLibEncoder(
|
||||
dictionary: hintString == null
|
||||
? null
|
||||
|
@ -231,10 +228,9 @@ class DevFSStringCompressingBytesContent extends DevFSContent {
|
|||
final ZLibEncoder _compressor;
|
||||
final DateTime _modificationTime = DateTime.now();
|
||||
|
||||
List<int> _bytes;
|
||||
bool _isModified = true;
|
||||
|
||||
List<int> get bytes => _bytes ??= _compressor.convert(utf8.encode(_string));
|
||||
late final List<int> bytes = _compressor.convert(utf8.encode(_string));
|
||||
|
||||
/// Return true only once so that the content is written to the device only once.
|
||||
@override
|
||||
|
@ -266,7 +262,7 @@ class DevFSException implements Exception {
|
|||
DevFSException(this.message, [this.error, this.stackTrace]);
|
||||
final String message;
|
||||
final dynamic error;
|
||||
final StackTrace stackTrace;
|
||||
final StackTrace? stackTrace;
|
||||
|
||||
@override
|
||||
String toString() => 'DevFSException($message, $error, $stackTrace)';
|
||||
|
@ -286,10 +282,10 @@ class _DevFSHttpWriter implements DevFSWriter {
|
|||
_DevFSHttpWriter(
|
||||
this.fsName,
|
||||
FlutterVmService serviceProtocol, {
|
||||
@required OperatingSystemUtils osUtils,
|
||||
@required HttpClient httpClient,
|
||||
@required Logger logger,
|
||||
Duration uploadRetryThrottle,
|
||||
required OperatingSystemUtils osUtils,
|
||||
required HttpClient httpClient,
|
||||
required Logger logger,
|
||||
Duration? uploadRetryThrottle,
|
||||
})
|
||||
: httpAddress = serviceProtocol.httpAddress,
|
||||
_client = httpClient,
|
||||
|
@ -300,10 +296,10 @@ class _DevFSHttpWriter implements DevFSWriter {
|
|||
final HttpClient _client;
|
||||
final OperatingSystemUtils _osUtils;
|
||||
final Logger _logger;
|
||||
final Duration _uploadRetryThrottle;
|
||||
final Duration? _uploadRetryThrottle;
|
||||
|
||||
final String fsName;
|
||||
final Uri httpAddress;
|
||||
final Uri? httpAddress;
|
||||
|
||||
// 3 was chosen to try to limit the variance in the time it takes to execute
|
||||
// `await request.close()` since there is a known bug in Dart where it doesn't
|
||||
|
@ -312,11 +308,11 @@ class _DevFSHttpWriter implements DevFSWriter {
|
|||
static const int kMaxInFlight = 3;
|
||||
|
||||
int _inFlight = 0;
|
||||
Map<Uri, DevFSContent> _outstanding = <Uri, DevFSContent>{};
|
||||
Completer<void> _completer = Completer<void>();
|
||||
late Map<Uri, DevFSContent> _outstanding;
|
||||
late Completer<void> _completer;
|
||||
|
||||
@override
|
||||
Future<void> write(Map<Uri, DevFSContent> entries, Uri devFSBase, [DevFSWriter parent]) async {
|
||||
Future<void> write(Map<Uri, DevFSContent> entries, Uri devFSBase, [DevFSWriter? parent]) async {
|
||||
try {
|
||||
_client.maxConnectionsPerHost = kMaxInFlight;
|
||||
_completer = Completer<void>();
|
||||
|
@ -335,7 +331,7 @@ class _DevFSHttpWriter implements DevFSWriter {
|
|||
void _scheduleWrites() {
|
||||
while ((_inFlight < kMaxInFlight) && (!_completer.isCompleted) && _outstanding.isNotEmpty) {
|
||||
final Uri deviceUri = _outstanding.keys.first;
|
||||
final DevFSContent content = _outstanding.remove(deviceUri);
|
||||
final DevFSContent content = _outstanding.remove(deviceUri)!;
|
||||
_startWrite(deviceUri, content, retry: 10);
|
||||
_inFlight += 1;
|
||||
}
|
||||
|
@ -351,7 +347,7 @@ class _DevFSHttpWriter implements DevFSWriter {
|
|||
}) async {
|
||||
while(true) {
|
||||
try {
|
||||
final HttpClientRequest request = await _client.putUrl(httpAddress);
|
||||
final HttpClientRequest request = await _client.putUrl(httpAddress!);
|
||||
request.headers.removeAll(HttpHeaders.acceptEncodingHeader);
|
||||
request.headers.add('dev_fs_name', fsName);
|
||||
request.headers.add('dev_fs_uri_b64', base64.encode(utf8.encode('$deviceUri')));
|
||||
|
@ -424,7 +420,7 @@ class UpdateFSReport {
|
|||
Duration get findInvalidatedDuration => _findInvalidatedDuration;
|
||||
|
||||
bool _success;
|
||||
String fastReassembleClassName;
|
||||
String? fastReassembleClassName;
|
||||
int _invalidatedSourcesCount;
|
||||
int _syncedBytes;
|
||||
int _scannedSourcesCount;
|
||||
|
@ -454,11 +450,11 @@ class DevFS {
|
|||
FlutterVmService serviceProtocol,
|
||||
this.fsName,
|
||||
this.rootDirectory, {
|
||||
@required OperatingSystemUtils osUtils,
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
HttpClient httpClient,
|
||||
Duration uploadRetryThrottle,
|
||||
required OperatingSystemUtils osUtils,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
HttpClient? httpClient,
|
||||
Duration? uploadRetryThrottle,
|
||||
StopwatchFactory stopwatchFactory = const StopwatchFactory(),
|
||||
}) : _vmService = serviceProtocol,
|
||||
_logger = logger,
|
||||
|
@ -471,7 +467,7 @@ class DevFS {
|
|||
uploadRetryThrottle: uploadRetryThrottle,
|
||||
httpClient: httpClient ?? ((context.get<HttpClientFactory>() == null)
|
||||
? HttpClient()
|
||||
: context.get<HttpClientFactory>()())),
|
||||
: context.get<HttpClientFactory>()!())),
|
||||
_stopwatchFactory = stopwatchFactory;
|
||||
|
||||
final FlutterVmService _vmService;
|
||||
|
@ -488,13 +484,13 @@ class DevFS {
|
|||
bool hasSetAssetDirectory = false;
|
||||
|
||||
List<Uri> sources = <Uri>[];
|
||||
DateTime lastCompiled;
|
||||
DateTime _previousCompiled;
|
||||
PackageConfig lastPackageConfig;
|
||||
File _widgetCacheOutputFile;
|
||||
DateTime? lastCompiled;
|
||||
DateTime? _previousCompiled;
|
||||
PackageConfig? lastPackageConfig;
|
||||
File? _widgetCacheOutputFile;
|
||||
|
||||
Uri _baseUri;
|
||||
Uri get baseUri => _baseUri;
|
||||
Uri? _baseUri;
|
||||
Uri? get baseUri => _baseUri;
|
||||
|
||||
Uri deviceUriToHostUri(Uri deviceUri) {
|
||||
final String deviceUriString = deviceUri.toString();
|
||||
|
@ -510,7 +506,7 @@ class DevFS {
|
|||
_logger.printTrace('DevFS: Creating new filesystem on the device ($_baseUri)');
|
||||
try {
|
||||
final vm_service.Response response = await _vmService.createDevFS(fsName);
|
||||
_baseUri = Uri.parse(response.json['uri'] as String);
|
||||
_baseUri = Uri.parse(response.json!['uri'] as String);
|
||||
} on vm_service.RPCError catch (rpcException) {
|
||||
if (rpcException.code == RPCErrorCodes.kServiceDisappeared) {
|
||||
// This can happen if the device has been disconnected, so translate to
|
||||
|
@ -526,10 +522,10 @@ class DevFS {
|
|||
_logger.printTrace('DevFS: Creating failed. Destroying and trying again');
|
||||
await destroy();
|
||||
final vm_service.Response response = await _vmService.createDevFS(fsName);
|
||||
_baseUri = Uri.parse(response.json['uri'] as String);
|
||||
_baseUri = Uri.parse(response.json!['uri'] as String);
|
||||
}
|
||||
_logger.printTrace('DevFS: Created new filesystem on the device ($_baseUri)');
|
||||
return _baseUri;
|
||||
return _baseUri!;
|
||||
}
|
||||
|
||||
Future<void> destroy() async {
|
||||
|
@ -556,8 +552,8 @@ class DevFS {
|
|||
///
|
||||
/// If any other changes were made, or there is an error scanning the file,
|
||||
/// return `null`.
|
||||
String _checkIfSingleWidgetReloadApplied() {
|
||||
final File widgetCacheOutputFile = _widgetCacheOutputFile;
|
||||
String? _checkIfSingleWidgetReloadApplied() {
|
||||
final File? widgetCacheOutputFile = _widgetCacheOutputFile;
|
||||
if (widgetCacheOutputFile != null && widgetCacheOutputFile.existsSync()) {
|
||||
final String widget = widgetCacheOutputFile.readAsStringSync().trim();
|
||||
if (widget.isNotEmpty) {
|
||||
|
@ -571,20 +567,20 @@ class DevFS {
|
|||
///
|
||||
/// Returns the number of bytes synced.
|
||||
Future<UpdateFSReport> update({
|
||||
@required Uri mainUri,
|
||||
@required ResidentCompiler generator,
|
||||
@required bool trackWidgetCreation,
|
||||
@required String pathToReload,
|
||||
@required List<Uri> invalidatedFiles,
|
||||
@required PackageConfig packageConfig,
|
||||
@required String dillOutputPath,
|
||||
DevFSWriter devFSWriter,
|
||||
String target,
|
||||
AssetBundle bundle,
|
||||
DateTime firstBuildTime,
|
||||
required Uri mainUri,
|
||||
required ResidentCompiler generator,
|
||||
required bool trackWidgetCreation,
|
||||
required String pathToReload,
|
||||
required List<Uri> invalidatedFiles,
|
||||
required PackageConfig packageConfig,
|
||||
required String dillOutputPath,
|
||||
DevFSWriter? devFSWriter,
|
||||
String? target,
|
||||
AssetBundle? bundle,
|
||||
DateTime? firstBuildTime,
|
||||
bool bundleFirstUpload = false,
|
||||
bool fullRestart = false,
|
||||
String projectRootPath,
|
||||
String? projectRootPath,
|
||||
}) async {
|
||||
assert(trackWidgetCreation != null);
|
||||
assert(generator != null);
|
||||
|
@ -606,7 +602,7 @@ class DevFS {
|
|||
// Await the compiler response after checking if the bundle is updated. This allows the file
|
||||
// stating to be done while waiting for the frontend_server response.
|
||||
final Stopwatch compileTimer = _stopwatchFactory.createStopwatch('compile')..start();
|
||||
final Future<CompilerOutput> pendingCompilerOutput = generator.recompile(
|
||||
final Future<CompilerOutput?> pendingCompilerOutput = generator.recompile(
|
||||
mainUri,
|
||||
invalidatedFiles,
|
||||
outputPath: dillOutputPath,
|
||||
|
@ -614,7 +610,7 @@ class DevFS {
|
|||
projectRootPath: projectRootPath,
|
||||
packageConfig: packageConfig,
|
||||
checkDartPluginRegistry: true, // The entry point is assumed not to have changed.
|
||||
).then((CompilerOutput result) {
|
||||
).then((CompilerOutput? result) {
|
||||
compileTimer.stop();
|
||||
return result;
|
||||
});
|
||||
|
@ -641,7 +637,7 @@ class DevFS {
|
|||
}
|
||||
});
|
||||
}
|
||||
final CompilerOutput compilerOutput = await pendingCompilerOutput;
|
||||
final CompilerOutput? compilerOutput = await pendingCompilerOutput;
|
||||
if (compilerOutput == null || compilerOutput.errorCount > 0) {
|
||||
return UpdateFSReport(success: false);
|
||||
}
|
||||
|
@ -654,8 +650,8 @@ class DevFS {
|
|||
// Don't send full kernel file that would overwrite what VM already
|
||||
// started loading from.
|
||||
if (!bundleFirstUpload) {
|
||||
final String compiledBinary = compilerOutput?.outputFilename;
|
||||
if (compiledBinary != null && compiledBinary.isNotEmpty) {
|
||||
final String compiledBinary = compilerOutput.outputFilename;
|
||||
if (compiledBinary.isNotEmpty) {
|
||||
final Uri entryUri = _fileSystem.path.toUri(pathToReload);
|
||||
final DevFSFileContent content = DevFSFileContent(_fileSystem.file(compiledBinary));
|
||||
syncedBytes += content.size;
|
||||
|
@ -665,7 +661,7 @@ class DevFS {
|
|||
_logger.printTrace('Updating files.');
|
||||
final Stopwatch transferTimer = _stopwatchFactory.createStopwatch('transfer')..start();
|
||||
if (dirtyEntries.isNotEmpty) {
|
||||
await (devFSWriter ?? _httpWriter).write(dirtyEntries, _baseUri, _httpWriter);
|
||||
await (devFSWriter ?? _httpWriter).write(dirtyEntries, _baseUri!, _httpWriter);
|
||||
}
|
||||
transferTimer.stop();
|
||||
_logger.printTrace('DevFS: Sync finished');
|
||||
|
@ -693,16 +689,17 @@ class DevFS {
|
|||
/// Requires that the file system is the same for both the tool and application.
|
||||
class LocalDevFSWriter implements DevFSWriter {
|
||||
LocalDevFSWriter({
|
||||
@required FileSystem fileSystem,
|
||||
required FileSystem fileSystem,
|
||||
}) : _fileSystem = fileSystem;
|
||||
|
||||
final FileSystem _fileSystem;
|
||||
|
||||
@override
|
||||
Future<void> write(Map<Uri, DevFSContent> entries, Uri baseUri, [DevFSWriter parent]) async {
|
||||
Future<void> write(Map<Uri, DevFSContent> entries, Uri baseUri, [DevFSWriter? parent]) async {
|
||||
try {
|
||||
for (final Uri uri in entries.keys) {
|
||||
final DevFSContent devFSContent = entries[uri];
|
||||
for (final MapEntry<Uri, DevFSContent> entry in entries.entries) {
|
||||
final Uri uri = entry.key;
|
||||
final DevFSContent devFSContent = entry.value;
|
||||
final File destination = _fileSystem.file(baseUri.resolveUri(uri));
|
||||
if (!destination.parent.existsSync()) {
|
||||
destination.parent.createSync(recursive: true);
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
|
@ -25,7 +23,7 @@ import 'device_port_forwarder.dart';
|
|||
import 'project.dart';
|
||||
import 'vmservice.dart';
|
||||
|
||||
DeviceManager get deviceManager => context.get<DeviceManager>();
|
||||
DeviceManager? get deviceManager => context.get<DeviceManager>();
|
||||
|
||||
/// A description of the kind of workflow the device supports.
|
||||
class Category {
|
||||
|
@ -63,9 +61,9 @@ class PlatformType {
|
|||
/// A discovery mechanism for flutter-supported development devices.
|
||||
abstract class DeviceManager {
|
||||
DeviceManager({
|
||||
@required Logger logger,
|
||||
@required Terminal terminal,
|
||||
@required UserMessages userMessages,
|
||||
required Logger logger,
|
||||
required Terminal terminal,
|
||||
required UserMessages userMessages,
|
||||
}) : _logger = logger,
|
||||
_terminal = terminal,
|
||||
_userMessages = userMessages;
|
||||
|
@ -78,17 +76,17 @@ abstract class DeviceManager {
|
|||
/// of their methods are called.
|
||||
List<DeviceDiscovery> get deviceDiscoverers;
|
||||
|
||||
String _specifiedDeviceId;
|
||||
String? _specifiedDeviceId;
|
||||
|
||||
/// A user-specified device ID.
|
||||
String get specifiedDeviceId {
|
||||
String? get specifiedDeviceId {
|
||||
if (_specifiedDeviceId == null || _specifiedDeviceId == 'all') {
|
||||
return null;
|
||||
}
|
||||
return _specifiedDeviceId;
|
||||
}
|
||||
|
||||
set specifiedDeviceId(String id) {
|
||||
set specifiedDeviceId(String? id) {
|
||||
_specifiedDeviceId = id;
|
||||
}
|
||||
|
||||
|
@ -120,7 +118,7 @@ abstract class DeviceManager {
|
|||
// found quickly, we don't wait for all the discoverers to complete.
|
||||
final List<Device> prefixMatches = <Device>[];
|
||||
final Completer<Device> exactMatchCompleter = Completer<Device>();
|
||||
final List<Future<List<Device>>> futureDevices = <Future<List<Device>>>[
|
||||
final List<Future<List<Device>?>> futureDevices = <Future<List<Device>?>>[
|
||||
for (final DeviceDiscovery discoverer in _platformDiscoverers)
|
||||
if (!hasWellKnownId || discoverer.wellKnownIds.contains(specifiedDeviceId))
|
||||
discoverer
|
||||
|
@ -143,9 +141,9 @@ abstract class DeviceManager {
|
|||
];
|
||||
|
||||
// Wait for an exact match, or for all discoverers to return results.
|
||||
await Future.any<dynamic>(<Future<dynamic>>[
|
||||
await Future.any<Object>(<Future<Object>>[
|
||||
exactMatchCompleter.future,
|
||||
Future.wait<List<Device>>(futureDevices),
|
||||
Future.wait<List<Device>?>(futureDevices),
|
||||
]);
|
||||
|
||||
if (exactMatchCompleter.isCompleted) {
|
||||
|
@ -156,9 +154,11 @@ abstract class DeviceManager {
|
|||
|
||||
/// Returns the list of connected devices, filtered by any user-specified device id.
|
||||
Future<List<Device>> getDevices() {
|
||||
return hasSpecifiedDeviceId
|
||||
? getDevicesById(specifiedDeviceId)
|
||||
: getAllConnectedDevices();
|
||||
final String? id = specifiedDeviceId;
|
||||
if (id == null) {
|
||||
return getAllConnectedDevices();
|
||||
}
|
||||
return getDevicesById(id);
|
||||
}
|
||||
|
||||
Iterable<DeviceDiscovery> get _platformDiscoverers {
|
||||
|
@ -176,7 +176,7 @@ abstract class DeviceManager {
|
|||
}
|
||||
|
||||
/// Returns the list of all connected devices. Discards existing cache of devices.
|
||||
Future<List<Device>> refreshAllConnectedDevices({ Duration timeout }) async {
|
||||
Future<List<Device>> refreshAllConnectedDevices({ Duration? timeout }) async {
|
||||
final List<List<Device>> devices = await Future.wait<List<Device>>(<Future<List<Device>>>[
|
||||
for (final DeviceDiscovery discoverer in _platformDiscoverers)
|
||||
discoverer.discoverDevices(timeout: timeout),
|
||||
|
@ -214,7 +214,7 @@ abstract class DeviceManager {
|
|||
///
|
||||
/// * If [flutterProject] is null, then assume the project supports all
|
||||
/// device types.
|
||||
Future<List<Device>> findTargetDevices(FlutterProject flutterProject, { Duration timeout }) async {
|
||||
Future<List<Device>> findTargetDevices(FlutterProject flutterProject, { Duration? timeout }) async {
|
||||
if (timeout != null) {
|
||||
// Reset the cache with the specified timeout.
|
||||
await refreshAllConnectedDevices(timeout: timeout);
|
||||
|
@ -338,7 +338,7 @@ abstract class DeviceDiscovery {
|
|||
Future<List<Device>> get devices;
|
||||
|
||||
/// Return all connected devices. Discards existing cache of devices.
|
||||
Future<List<Device>> discoverDevices({ Duration timeout });
|
||||
Future<List<Device>> discoverDevices({ Duration? timeout });
|
||||
|
||||
/// Gets a list of diagnostic messages pertaining to issues with any connected
|
||||
/// devices (will be an empty list if there are no issues).
|
||||
|
@ -366,11 +366,11 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
|
|||
|
||||
@protected
|
||||
@visibleForTesting
|
||||
ItemListNotifier<Device> deviceNotifier;
|
||||
ItemListNotifier<Device>? deviceNotifier;
|
||||
|
||||
Timer _timer;
|
||||
Timer? _timer;
|
||||
|
||||
Future<List<Device>> pollingGetDevices({ Duration timeout });
|
||||
Future<List<Device>> pollingGetDevices({ Duration? timeout });
|
||||
|
||||
void startPolling() {
|
||||
if (_timer == null) {
|
||||
|
@ -380,11 +380,11 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
|
|||
}
|
||||
}
|
||||
|
||||
Timer _initTimer(Duration pollingTimeout) {
|
||||
Timer _initTimer(Duration? pollingTimeout) {
|
||||
return Timer(_pollingInterval, () async {
|
||||
try {
|
||||
final List<Device> devices = await pollingGetDevices(timeout: pollingTimeout);
|
||||
deviceNotifier.updateWithNewList(devices);
|
||||
deviceNotifier!.updateWithNewList(devices);
|
||||
} on TimeoutException {
|
||||
// Do nothing on a timeout.
|
||||
}
|
||||
|
@ -404,24 +404,24 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<Device>> discoverDevices({ Duration timeout }) {
|
||||
Future<List<Device>> discoverDevices({ Duration? timeout }) {
|
||||
deviceNotifier = null;
|
||||
return _populateDevices(timeout: timeout);
|
||||
}
|
||||
|
||||
Future<List<Device>> _populateDevices({ Duration timeout }) async {
|
||||
Future<List<Device>> _populateDevices({ Duration? timeout }) async {
|
||||
deviceNotifier ??= ItemListNotifier<Device>.from(await pollingGetDevices(timeout: timeout));
|
||||
return deviceNotifier.items;
|
||||
return deviceNotifier!.items;
|
||||
}
|
||||
|
||||
Stream<Device> get onAdded {
|
||||
deviceNotifier ??= ItemListNotifier<Device>();
|
||||
return deviceNotifier.onAdded;
|
||||
return deviceNotifier!.onAdded;
|
||||
}
|
||||
|
||||
Stream<Device> get onRemoved {
|
||||
deviceNotifier ??= ItemListNotifier<Device>();
|
||||
return deviceNotifier.onRemoved;
|
||||
return deviceNotifier!.onRemoved;
|
||||
}
|
||||
|
||||
void dispose() => stopPolling();
|
||||
|
@ -436,9 +436,9 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
|
|||
/// the host operating system in the case of Flutter Desktop.
|
||||
abstract class Device {
|
||||
Device(this.id, {
|
||||
@required this.category,
|
||||
@required this.platformType,
|
||||
@required this.ephemeral,
|
||||
required this.category,
|
||||
required this.platformType,
|
||||
required this.ephemeral,
|
||||
});
|
||||
|
||||
final String id;
|
||||
|
@ -534,7 +534,7 @@ abstract class Device {
|
|||
///
|
||||
/// For example, the desktop device classes can use a writer which
|
||||
/// copies the files across the local file system.
|
||||
DevFSWriter createDevFSWriter(
|
||||
DevFSWriter? createDevFSWriter(
|
||||
covariant ApplicationPackage app,
|
||||
String userIdentifier,
|
||||
) {
|
||||
|
@ -564,7 +564,7 @@ abstract class Device {
|
|||
void clearLogs();
|
||||
|
||||
/// Optional device-specific artifact overrides.
|
||||
OverrideArtifacts get artifactOverrides => null;
|
||||
OverrideArtifacts? get artifactOverrides => null;
|
||||
|
||||
/// Start an app package on the current device.
|
||||
///
|
||||
|
@ -575,7 +575,7 @@ abstract class Device {
|
|||
String mainPath,
|
||||
String route,
|
||||
DebuggingOptions debuggingOptions,
|
||||
Map<String, dynamic> platformArgs,
|
||||
Map<String, Object?> platformArgs,
|
||||
bool prebuiltApplication = false,
|
||||
bool ipv6 = false,
|
||||
String userIdentifier,
|
||||
|
@ -817,8 +817,8 @@ class DebuggingOptions {
|
|||
final bool enableSoftwareRendering;
|
||||
final bool skiaDeterministicRendering;
|
||||
final bool traceSkia;
|
||||
final String traceAllowlist;
|
||||
final String traceSkiaAllowlist;
|
||||
final String? traceAllowlist;
|
||||
final String? traceSkiaAllowlist;
|
||||
final bool traceSystrace;
|
||||
final bool endlessTraceBuffer;
|
||||
final bool dumpSkpOnShaderCompilation;
|
||||
|
@ -826,14 +826,14 @@ class DebuggingOptions {
|
|||
final bool purgePersistentCache;
|
||||
final bool useTestFonts;
|
||||
final bool verboseSystemLogs;
|
||||
final int hostVmServicePort;
|
||||
final int deviceVmServicePort;
|
||||
final int? hostVmServicePort;
|
||||
final int? deviceVmServicePort;
|
||||
final bool disablePortPublication;
|
||||
final int ddsPort;
|
||||
final Uri devToolsServerAddress;
|
||||
final String port;
|
||||
final String hostname;
|
||||
final bool webEnableExposeUrl;
|
||||
final int? ddsPort;
|
||||
final Uri? devToolsServerAddress;
|
||||
final String? port;
|
||||
final String? hostname;
|
||||
final bool? webEnableExposeUrl;
|
||||
final bool webUseSseForDebugProxy;
|
||||
final bool webUseSseForDebugBackend;
|
||||
final bool webUseSseForInjectedClient;
|
||||
|
@ -846,13 +846,13 @@ class DebuggingOptions {
|
|||
final bool webRunHeadless;
|
||||
|
||||
/// The port the browser should use for its debugging protocol.
|
||||
final int webBrowserDebugPort;
|
||||
final int? webBrowserDebugPort;
|
||||
|
||||
/// Enable expression evaluation for web target.
|
||||
final bool webEnableExpressionEvaluation;
|
||||
|
||||
/// A file where the VM Service URL should be written after the application is started.
|
||||
final String vmserviceOutFile;
|
||||
final String? vmserviceOutFile;
|
||||
final bool fastStart;
|
||||
|
||||
final bool nullAssertions;
|
||||
|
@ -875,7 +875,7 @@ class LaunchResult {
|
|||
bool get hasObservatory => observatoryUri != null;
|
||||
|
||||
final bool started;
|
||||
final Uri observatoryUri;
|
||||
final Uri? observatoryUri;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
@ -896,13 +896,13 @@ abstract class DeviceLogReader {
|
|||
|
||||
/// Some logs can be obtained from a VM service stream.
|
||||
/// Set this after the VM services are connected.
|
||||
FlutterVmService connectedVMService;
|
||||
FlutterVmService? connectedVMService;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
|
||||
/// Process ID of the app on the device.
|
||||
int appPid;
|
||||
int? appPid;
|
||||
|
||||
// Clean up resources allocated by log reader e.g. subprocesses
|
||||
void dispose();
|
||||
|
@ -923,10 +923,10 @@ class NoOpDeviceLogReader implements DeviceLogReader {
|
|||
final String name;
|
||||
|
||||
@override
|
||||
int appPid;
|
||||
int? appPid;
|
||||
|
||||
@override
|
||||
FlutterVmService connectedVMService;
|
||||
FlutterVmService? connectedVMService;
|
||||
|
||||
@override
|
||||
Stream<String> get logLines => const Stream<String>.empty();
|
||||
|
@ -939,7 +939,7 @@ class NoOpDeviceLogReader implements DeviceLogReader {
|
|||
/// [debuggingOptions.nullAssertions] is true.
|
||||
String computeDartVmFlags(DebuggingOptions debuggingOptions) {
|
||||
return <String>[
|
||||
if (debuggingOptions.dartFlags?.isNotEmpty ?? false)
|
||||
if (debuggingOptions.dartFlags.isNotEmpty)
|
||||
debuggingOptions.dartFlags,
|
||||
if (debuggingOptions.nullAssertions)
|
||||
'--null_assertions',
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart' show required, visibleForTesting;
|
||||
import 'package:meta/meta.dart' show visibleForTesting;
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import 'base/common.dart';
|
||||
|
@ -31,7 +29,7 @@ const int kIsolateReloadBarred = 1005;
|
|||
|
||||
/// Override `WebSocketConnector` in [context] to use a different constructor
|
||||
/// for [WebSocket]s (used by tests).
|
||||
typedef WebSocketConnector = Future<io.WebSocket> Function(String url, {io.CompressionOptions compression, @required Logger logger});
|
||||
typedef WebSocketConnector = Future<io.WebSocket> Function(String url, {io.CompressionOptions compression, required Logger logger});
|
||||
|
||||
typedef PrintStructuredErrorLogMethod = void Function(vm_service.Event);
|
||||
|
||||
|
@ -41,7 +39,7 @@ WebSocketConnector _openChannel = _defaultOpenChannel;
|
|||
///
|
||||
/// Provide a `null` value to restore the original connector.
|
||||
@visibleForTesting
|
||||
set openChannelForTesting(WebSocketConnector connector) {
|
||||
set openChannelForTesting(WebSocketConnector? connector) {
|
||||
_openChannel = connector ?? _defaultOpenChannel;
|
||||
}
|
||||
|
||||
|
@ -93,7 +91,7 @@ typedef CompileExpression = Future<String> Function(
|
|||
List<String> definitions,
|
||||
List<String> typeDefinitions,
|
||||
String libraryUri,
|
||||
String klass,
|
||||
String? klass,
|
||||
bool isStatic,
|
||||
);
|
||||
|
||||
|
@ -104,13 +102,13 @@ typedef GetSkSLMethod = Future<String> Function();
|
|||
|
||||
Future<io.WebSocket> _defaultOpenChannel(String url, {
|
||||
io.CompressionOptions compression = io.CompressionOptions.compressionDefault,
|
||||
@required Logger logger,
|
||||
required Logger logger,
|
||||
}) async {
|
||||
Duration delay = const Duration(milliseconds: 100);
|
||||
int attempts = 0;
|
||||
io.WebSocket socket;
|
||||
io.WebSocket? socket;
|
||||
|
||||
Future<void> handleError(dynamic e) async {
|
||||
Future<void> handleError(Object? e) async {
|
||||
void Function(String) printVisibleTrace = logger.printTrace;
|
||||
if (attempts == 10) {
|
||||
logger.printStatus('Connecting to the VM Service is taking longer than expected...');
|
||||
|
@ -142,7 +140,7 @@ Future<io.WebSocket> _defaultOpenChannel(String url, {
|
|||
|
||||
final WebSocketConnector constructor = context.get<WebSocketConnector>() ?? (String url, {
|
||||
io.CompressionOptions compression = io.CompressionOptions.compressionDefault,
|
||||
@required Logger logger,
|
||||
Logger? logger,
|
||||
}) => io.WebSocket.connect(url, compression: compression);
|
||||
|
||||
while (socket == null) {
|
||||
|
@ -161,14 +159,14 @@ Future<io.WebSocket> _defaultOpenChannel(String url, {
|
|||
/// Override `VMServiceConnector` in [context] to return a different VMService
|
||||
/// from [VMService.connect] (used by tests).
|
||||
typedef VMServiceConnector = Future<FlutterVmService> Function(Uri httpUri, {
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
CompileExpression compileExpression,
|
||||
GetSkSLMethod getSkSLMethod,
|
||||
PrintStructuredErrorLogMethod printStructuredErrorLogMethod,
|
||||
ReloadSources? reloadSources,
|
||||
Restart? restart,
|
||||
CompileExpression? compileExpression,
|
||||
GetSkSLMethod? getSkSLMethod,
|
||||
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
|
||||
io.CompressionOptions compression,
|
||||
Device device,
|
||||
@required Logger logger,
|
||||
Device? device,
|
||||
required Logger logger,
|
||||
});
|
||||
|
||||
/// Set up the VM Service client by attaching services for each of the provided
|
||||
|
@ -176,12 +174,12 @@ typedef VMServiceConnector = Future<FlutterVmService> Function(Uri httpUri, {
|
|||
///
|
||||
/// All parameters besides [vmService] may be null.
|
||||
Future<vm_service.VmService> setUpVmService(
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
CompileExpression compileExpression,
|
||||
Device device,
|
||||
GetSkSLMethod skSLMethod,
|
||||
PrintStructuredErrorLogMethod printStructuredErrorLogMethod,
|
||||
ReloadSources? reloadSources,
|
||||
Restart? restart,
|
||||
CompileExpression? compileExpression,
|
||||
Device? device,
|
||||
GetSkSLMethod? skSLMethod,
|
||||
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
|
||||
vm_service.VmService vmService
|
||||
) async {
|
||||
// Each service registration requires a request to the attached VM service. Since the
|
||||
|
@ -189,14 +187,14 @@ Future<vm_service.VmService> setUpVmService(
|
|||
// all at the end of this method.
|
||||
final List<Future<vm_service.Success>> registrationRequests = <Future<vm_service.Success>>[];
|
||||
if (reloadSources != null) {
|
||||
vmService.registerServiceCallback('reloadSources', (Map<String, dynamic> params) async {
|
||||
vmService.registerServiceCallback('reloadSources', (Map<String, Object?> params) async {
|
||||
final String isolateId = _validateRpcStringParam('reloadSources', params, 'isolateId');
|
||||
final bool force = _validateRpcBoolParam('reloadSources', params, 'force');
|
||||
final bool pause = _validateRpcBoolParam('reloadSources', params, 'pause');
|
||||
|
||||
await reloadSources(isolateId, force: force, pause: pause);
|
||||
|
||||
return <String, dynamic>{
|
||||
return <String, Object>{
|
||||
'result': <String, Object>{
|
||||
'type': 'Success',
|
||||
}
|
||||
|
@ -206,10 +204,10 @@ Future<vm_service.VmService> setUpVmService(
|
|||
}
|
||||
|
||||
if (restart != null) {
|
||||
vmService.registerServiceCallback('hotRestart', (Map<String, dynamic> params) async {
|
||||
vmService.registerServiceCallback('hotRestart', (Map<String, Object?> params) async {
|
||||
final bool pause = _validateRpcBoolParam('compileExpression', params, 'pause');
|
||||
await restart(pause: pause);
|
||||
return <String, dynamic>{
|
||||
return <String, Object>{
|
||||
'result': <String, Object>{
|
||||
'type': 'Success',
|
||||
}
|
||||
|
@ -218,12 +216,12 @@ Future<vm_service.VmService> setUpVmService(
|
|||
registrationRequests.add(vmService.registerService('hotRestart', 'Flutter Tools'));
|
||||
}
|
||||
|
||||
vmService.registerServiceCallback('flutterVersion', (Map<String, dynamic> params) async {
|
||||
vmService.registerServiceCallback('flutterVersion', (Map<String, Object?> params) async {
|
||||
final FlutterVersion version = context.get<FlutterVersion>() ?? FlutterVersion();
|
||||
final Map<String, Object> versionJson = version.toJson();
|
||||
versionJson['frameworkRevisionShort'] = version.frameworkRevisionShort;
|
||||
versionJson['engineRevisionShort'] = version.engineRevisionShort;
|
||||
return <String, dynamic>{
|
||||
return <String, Object>{
|
||||
'result': <String, Object>{
|
||||
'type': 'Success',
|
||||
...versionJson,
|
||||
|
@ -233,29 +231,29 @@ Future<vm_service.VmService> setUpVmService(
|
|||
registrationRequests.add(vmService.registerService('flutterVersion', 'Flutter Tools'));
|
||||
|
||||
if (compileExpression != null) {
|
||||
vmService.registerServiceCallback('compileExpression', (Map<String, dynamic> params) async {
|
||||
vmService.registerServiceCallback('compileExpression', (Map<String, Object?> params) async {
|
||||
final String isolateId = _validateRpcStringParam('compileExpression', params, 'isolateId');
|
||||
final String expression = _validateRpcStringParam('compileExpression', params, 'expression');
|
||||
final List<String> definitions = List<String>.from(params['definitions'] as List<dynamic>);
|
||||
final List<String> typeDefinitions = List<String>.from(params['typeDefinitions'] as List<dynamic>);
|
||||
final String libraryUri = params['libraryUri'] as String;
|
||||
final String klass = params['klass'] as String;
|
||||
final List<String> definitions = List<String>.from(params['definitions']! as List<Object?>);
|
||||
final List<String> typeDefinitions = List<String>.from(params['typeDefinitions']! as List<Object?>);
|
||||
final String libraryUri = params['libraryUri']! as String;
|
||||
final String? klass = params['klass'] as String?;
|
||||
final bool isStatic = _validateRpcBoolParam('compileExpression', params, 'isStatic');
|
||||
|
||||
final String kernelBytesBase64 = await compileExpression(isolateId,
|
||||
expression, definitions, typeDefinitions, libraryUri, klass,
|
||||
isStatic);
|
||||
return <String, dynamic>{
|
||||
return <String, Object>{
|
||||
'type': 'Success',
|
||||
'result': <String, dynamic>{'kernelBytes': kernelBytesBase64},
|
||||
'result': <String, String>{'kernelBytes': kernelBytesBase64},
|
||||
};
|
||||
});
|
||||
registrationRequests.add(vmService.registerService('compileExpression', 'Flutter Tools'));
|
||||
}
|
||||
if (device != null) {
|
||||
vmService.registerServiceCallback('flutterMemoryInfo', (Map<String, dynamic> params) async {
|
||||
vmService.registerServiceCallback('flutterMemoryInfo', (Map<String, Object?> params) async {
|
||||
final MemoryInfo result = await device.queryMemoryInfo();
|
||||
return <String, dynamic>{
|
||||
return <String, Object>{
|
||||
'result': <String, Object>{
|
||||
'type': 'Success',
|
||||
...result.toJson(),
|
||||
|
@ -265,9 +263,9 @@ Future<vm_service.VmService> setUpVmService(
|
|||
registrationRequests.add(vmService.registerService('flutterMemoryInfo', 'Flutter Tools'));
|
||||
}
|
||||
if (skSLMethod != null) {
|
||||
vmService.registerServiceCallback('flutterGetSkSL', (Map<String, dynamic> params) async {
|
||||
vmService.registerServiceCallback('flutterGetSkSL', (Map<String, Object?> params) async {
|
||||
final String filename = await skSLMethod();
|
||||
return <String, dynamic>{
|
||||
return <String, Object>{
|
||||
'result': <String, Object>{
|
||||
'type': 'Success',
|
||||
'filename': filename,
|
||||
|
@ -282,7 +280,7 @@ Future<vm_service.VmService> setUpVmService(
|
|||
// thrown if we're already subscribed.
|
||||
registrationRequests.add(vmService
|
||||
.streamListen(vm_service.EventStreams.kExtension)
|
||||
.catchError((dynamic error) {}, test: (dynamic error) => error is vm_service.RPCError)
|
||||
.catchError((Object? error) {}, test: (Object? error) => error is vm_service.RPCError)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -304,14 +302,14 @@ Future<vm_service.VmService> setUpVmService(
|
|||
/// See: https://github.com/dart-lang/sdk/commit/df8bf384eb815cf38450cb50a0f4b62230fba217
|
||||
Future<FlutterVmService> connectToVmService(
|
||||
Uri httpUri, {
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
CompileExpression compileExpression,
|
||||
GetSkSLMethod getSkSLMethod,
|
||||
PrintStructuredErrorLogMethod printStructuredErrorLogMethod,
|
||||
ReloadSources? reloadSources,
|
||||
Restart? restart,
|
||||
CompileExpression? compileExpression,
|
||||
GetSkSLMethod? getSkSLMethod,
|
||||
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
|
||||
io.CompressionOptions compression = io.CompressionOptions.compressionDefault,
|
||||
Device device,
|
||||
@required Logger logger,
|
||||
Device? device,
|
||||
required Logger logger,
|
||||
}) async {
|
||||
final VMServiceConnector connector = context.get<VMServiceConnector>() ?? _connect;
|
||||
return connector(httpUri,
|
||||
|
@ -329,7 +327,7 @@ Future<FlutterVmService> connectToVmService(
|
|||
Future<vm_service.VmService> createVmServiceDelegate(
|
||||
Uri wsUri, {
|
||||
io.CompressionOptions compression = io.CompressionOptions.compressionDefault,
|
||||
@required Logger logger,
|
||||
required Logger logger,
|
||||
}) async {
|
||||
final io.WebSocket channel = await _openChannel(wsUri.toString(), compression: compression, logger: logger);
|
||||
return vm_service.VmService(
|
||||
|
@ -344,14 +342,14 @@ Future<vm_service.VmService> createVmServiceDelegate(
|
|||
|
||||
Future<FlutterVmService> _connect(
|
||||
Uri httpUri, {
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
CompileExpression compileExpression,
|
||||
GetSkSLMethod getSkSLMethod,
|
||||
PrintStructuredErrorLogMethod printStructuredErrorLogMethod,
|
||||
ReloadSources? reloadSources,
|
||||
Restart? restart,
|
||||
CompileExpression? compileExpression,
|
||||
GetSkSLMethod? getSkSLMethod,
|
||||
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
|
||||
io.CompressionOptions compression = io.CompressionOptions.compressionDefault,
|
||||
Device device,
|
||||
@required Logger logger,
|
||||
Device? device,
|
||||
required Logger logger,
|
||||
}) async {
|
||||
final Uri wsUri = httpUri.replace(scheme: 'ws', path: urlContext.join(httpUri.path, 'ws'));
|
||||
final vm_service.VmService delegateService = await createVmServiceDelegate(
|
||||
|
@ -374,20 +372,20 @@ Future<FlutterVmService> _connect(
|
|||
return FlutterVmService(service, httpAddress: httpUri, wsAddress: wsUri);
|
||||
}
|
||||
|
||||
String _validateRpcStringParam(String methodName, Map<String, dynamic> params, String paramName) {
|
||||
final dynamic value = params[paramName];
|
||||
if (value is! String || (value as String).isEmpty) {
|
||||
String _validateRpcStringParam(String methodName, Map<String, Object?> params, String paramName) {
|
||||
final Object? value = params[paramName];
|
||||
if (value is! String || value.isEmpty) {
|
||||
throw vm_service.RPCError(
|
||||
methodName,
|
||||
RPCErrorCodes.kInvalidParams,
|
||||
"Invalid '$paramName': $value",
|
||||
);
|
||||
}
|
||||
return value as String;
|
||||
return value;
|
||||
}
|
||||
|
||||
bool _validateRpcBoolParam(String methodName, Map<String, dynamic> params, String paramName) {
|
||||
final dynamic value = params[paramName];
|
||||
bool _validateRpcBoolParam(String methodName, Map<String, Object?> params, String paramName) {
|
||||
final Object? value = params[paramName];
|
||||
if (value != null && value is! bool) {
|
||||
throw vm_service.RPCError(
|
||||
methodName,
|
||||
|
@ -395,30 +393,30 @@ bool _validateRpcBoolParam(String methodName, Map<String, dynamic> params, Strin
|
|||
"Invalid '$paramName': $value",
|
||||
);
|
||||
}
|
||||
return (value as bool) ?? false;
|
||||
return (value as bool?) ?? false;
|
||||
}
|
||||
|
||||
/// Peered to an Android/iOS FlutterView widget on a device.
|
||||
class FlutterView {
|
||||
FlutterView({
|
||||
@required this.id,
|
||||
@required this.uiIsolate,
|
||||
required this.id,
|
||||
required this.uiIsolate,
|
||||
});
|
||||
|
||||
factory FlutterView.parse(Map<String, Object> json) {
|
||||
final Map<String, Object> rawIsolate = json['isolate'] as Map<String, Object>;
|
||||
vm_service.IsolateRef isolate;
|
||||
final Map<String, Object?>? rawIsolate = json['isolate'] as Map<String, Object?>?;
|
||||
vm_service.IsolateRef? isolate;
|
||||
if (rawIsolate != null) {
|
||||
rawIsolate['number'] = rawIsolate['number']?.toString();
|
||||
isolate = vm_service.IsolateRef.parse(rawIsolate);
|
||||
}
|
||||
return FlutterView(
|
||||
id: json['id'] as String,
|
||||
id: json['id']! as String,
|
||||
uiIsolate: isolate,
|
||||
);
|
||||
}
|
||||
|
||||
final vm_service.IsolateRef uiIsolate;
|
||||
final vm_service.IsolateRef? uiIsolate;
|
||||
final String id;
|
||||
|
||||
bool get hasIsolate => uiIsolate != null;
|
||||
|
@ -426,8 +424,8 @@ class FlutterView {
|
|||
@override
|
||||
String toString() => id;
|
||||
|
||||
Map<String, Object> toJson() {
|
||||
return <String, Object>{
|
||||
Map<String, Object?> toJson() {
|
||||
return <String, Object?>{
|
||||
'id': id,
|
||||
'isolate': uiIsolate?.toJson(),
|
||||
};
|
||||
|
@ -436,16 +434,20 @@ class FlutterView {
|
|||
|
||||
/// Flutter specific VM Service functionality.
|
||||
class FlutterVmService {
|
||||
FlutterVmService(this.service, {this.wsAddress, this.httpAddress});
|
||||
FlutterVmService(
|
||||
this.service, {
|
||||
this.wsAddress,
|
||||
this.httpAddress,
|
||||
});
|
||||
|
||||
final vm_service.VmService service;
|
||||
final Uri wsAddress;
|
||||
final Uri httpAddress;
|
||||
final Uri? wsAddress;
|
||||
final Uri? httpAddress;
|
||||
|
||||
Future<vm_service.Response> callMethodWrapper(
|
||||
Future<vm_service.Response?> callMethodWrapper(
|
||||
String method, {
|
||||
String isolateId,
|
||||
Map<String, dynamic> args
|
||||
String? isolateId,
|
||||
Map<String, Object?>? args
|
||||
}) async {
|
||||
try {
|
||||
return await service.callMethod(method, isolateId: isolateId, args: args);
|
||||
|
@ -463,14 +465,13 @@ class FlutterVmService {
|
|||
|
||||
/// Set the asset directory for the an attached Flutter view.
|
||||
Future<void> setAssetDirectory({
|
||||
@required Uri assetsDirectory,
|
||||
@required String viewId,
|
||||
@required String uiIsolateId,
|
||||
required Uri assetsDirectory,
|
||||
required String? viewId,
|
||||
required String? uiIsolateId,
|
||||
}) async {
|
||||
assert(assetsDirectory != null);
|
||||
await callMethodWrapper(kSetAssetBundlePathMethod,
|
||||
isolateId: uiIsolateId,
|
||||
args: <String, dynamic>{
|
||||
args: <String, Object?>{
|
||||
'viewId': viewId,
|
||||
'assetDirectory': assetsDirectory.toFilePath(windows: false),
|
||||
});
|
||||
|
@ -480,10 +481,10 @@ class FlutterVmService {
|
|||
///
|
||||
/// This method will only return data if `--cache-sksl` was provided as a
|
||||
/// flutter run argument, and only then on physical devices.
|
||||
Future<Map<String, Object>> getSkSLs({
|
||||
@required String viewId,
|
||||
Future<Map<String, Object>?> getSkSLs({
|
||||
required String viewId,
|
||||
}) async {
|
||||
final vm_service.Response response = await callMethodWrapper(
|
||||
final vm_service.Response? response = await callMethodWrapper(
|
||||
kGetSkSLsMethod,
|
||||
args: <String, String>{
|
||||
'viewId': viewId,
|
||||
|
@ -492,14 +493,14 @@ class FlutterVmService {
|
|||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
return response.json['SkSLs'] as Map<String, Object>;
|
||||
return response.json?['SkSLs'] as Map<String, Object>?;
|
||||
}
|
||||
|
||||
/// Flush all tasks on the UI thread for an attached Flutter view.
|
||||
///
|
||||
/// This method is currently used only for benchmarking.
|
||||
Future<void> flushUIThreadTasks({
|
||||
@required String uiIsolateId,
|
||||
required String uiIsolateId,
|
||||
}) async {
|
||||
await callMethodWrapper(
|
||||
kFlushUIThreadTasksMethod,
|
||||
|
@ -515,9 +516,9 @@ class FlutterVmService {
|
|||
/// This method is used by the tool to hot restart an already running Flutter
|
||||
/// engine.
|
||||
Future<void> runInView({
|
||||
@required String viewId,
|
||||
@required Uri main,
|
||||
@required Uri assetsDirectory,
|
||||
required String viewId,
|
||||
required Uri main,
|
||||
required Uri assetsDirectory,
|
||||
}) async {
|
||||
try {
|
||||
await service.streamListen(vm_service.EventStreams.kIsolate);
|
||||
|
@ -539,60 +540,63 @@ class FlutterVmService {
|
|||
}
|
||||
|
||||
Future<String> flutterDebugDumpApp({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, Object> response = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? response = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.debugDumpApp',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
return response != null ? response['data']?.toString() : '';
|
||||
return response?['data']?.toString() ?? '';
|
||||
}
|
||||
|
||||
Future<String> flutterDebugDumpRenderTree({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, Object> response = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? response = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.debugDumpRenderTree',
|
||||
isolateId: isolateId,
|
||||
args: <String, Object>{}
|
||||
);
|
||||
return response != null ? response['data']?.toString() : '';
|
||||
return response?['data']?.toString() ?? '';
|
||||
}
|
||||
|
||||
Future<String> flutterDebugDumpLayerTree({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, Object> response = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? response = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.debugDumpLayerTree',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
return response != null ? response['data']?.toString() : '';
|
||||
return response?['data']?.toString() ?? '';
|
||||
}
|
||||
|
||||
Future<String> flutterDebugDumpSemanticsTreeInTraversalOrder({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, Object> response = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? response = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.debugDumpSemanticsTreeInTraversalOrder',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
return response != null ? response['data']?.toString() : '';
|
||||
return response?['data']?.toString() ?? '';
|
||||
}
|
||||
|
||||
Future<String> flutterDebugDumpSemanticsTreeInInverseHitTestOrder({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, Object> response = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? response = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
return response != null ? response['data']?.toString() : '';
|
||||
if (response != null) {
|
||||
return response['data']?.toString() ?? '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _flutterToggle(String name, {
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> _flutterToggle(String name, {
|
||||
required String isolateId,
|
||||
}) async {
|
||||
Map<String, dynamic> state = await invokeFlutterExtensionRpcRaw(
|
||||
Map<String, Object?>? state = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.$name',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
|
@ -600,7 +604,7 @@ class FlutterVmService {
|
|||
state = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.$name',
|
||||
isolateId: isolateId,
|
||||
args: <String, dynamic>{
|
||||
args: <String, Object>{
|
||||
'enabled': state['enabled'] == 'true' ? 'false' : 'true',
|
||||
},
|
||||
);
|
||||
|
@ -609,38 +613,38 @@ class FlutterVmService {
|
|||
return state;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> flutterToggleDebugPaintSizeEnabled({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterToggleDebugPaintSizeEnabled({
|
||||
required String isolateId,
|
||||
}) => _flutterToggle('debugPaint', isolateId: isolateId);
|
||||
|
||||
Future<Map<String, dynamic>> flutterTogglePerformanceOverlayOverride({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterTogglePerformanceOverlayOverride({
|
||||
required String isolateId,
|
||||
}) => _flutterToggle('showPerformanceOverlay', isolateId: isolateId);
|
||||
|
||||
Future<Map<String, dynamic>> flutterToggleWidgetInspector({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterToggleWidgetInspector({
|
||||
required String isolateId,
|
||||
}) => _flutterToggle('inspector.show', isolateId: isolateId);
|
||||
|
||||
Future<Map<String,dynamic>> flutterToggleInvertOversizedImages({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterToggleInvertOversizedImages({
|
||||
required String isolateId,
|
||||
}) => _flutterToggle('invertOversizedImages', isolateId: isolateId);
|
||||
|
||||
Future<Map<String, dynamic>> flutterToggleProfileWidgetBuilds({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterToggleProfileWidgetBuilds({
|
||||
required String isolateId,
|
||||
}) => _flutterToggle('profileWidgetBuilds', isolateId: isolateId);
|
||||
|
||||
Future<Map<String, dynamic>> flutterDebugAllowBanner(bool show, {
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterDebugAllowBanner(bool show, {
|
||||
required String isolateId,
|
||||
}) {
|
||||
return invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.debugAllowBanner',
|
||||
isolateId: isolateId,
|
||||
args: <String, dynamic>{'enabled': show ? 'true' : 'false'},
|
||||
args: <String, Object>{'enabled': show ? 'true' : 'false'},
|
||||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> flutterReassemble({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterReassemble({
|
||||
required String isolateId,
|
||||
}) {
|
||||
return invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.reassemble',
|
||||
|
@ -648,9 +652,9 @@ class FlutterVmService {
|
|||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> flutterFastReassemble({
|
||||
@required String isolateId,
|
||||
@required String className,
|
||||
Future<Map<String, Object?>?> flutterFastReassemble({
|
||||
required String isolateId,
|
||||
required String className,
|
||||
}) {
|
||||
return invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.fastReassemble',
|
||||
|
@ -662,18 +666,18 @@ class FlutterVmService {
|
|||
}
|
||||
|
||||
Future<bool> flutterAlreadyPaintedFirstUsefulFrame({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? result = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.didSendFirstFrameRasterizedEvent',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
// result might be null when the service extension is not initialized
|
||||
return result != null && result['enabled'] == 'true';
|
||||
return result?['enabled'] == 'true';
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> uiWindowScheduleFrame({
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> uiWindowScheduleFrame({
|
||||
required String isolateId,
|
||||
}) {
|
||||
return invokeFlutterExtensionRpcRaw(
|
||||
'ext.ui.window.scheduleFrame',
|
||||
|
@ -681,13 +685,13 @@ class FlutterVmService {
|
|||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> flutterEvictAsset(String assetPath, {
|
||||
@required String isolateId,
|
||||
Future<Map<String, Object?>?> flutterEvictAsset(String assetPath, {
|
||||
required String isolateId,
|
||||
}) {
|
||||
return invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.evict',
|
||||
isolateId: isolateId,
|
||||
args: <String, dynamic>{
|
||||
args: <String, Object?>{
|
||||
'value': assetPath,
|
||||
},
|
||||
);
|
||||
|
@ -698,10 +702,10 @@ class FlutterVmService {
|
|||
/// This method is only supported by certain embedders. This is
|
||||
/// described by [Device.supportsFlutterExit].
|
||||
Future<bool> flutterExit({
|
||||
@required String isolateId,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
try {
|
||||
final Map<String, Object> result = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? result = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.exit',
|
||||
isolateId: isolateId,
|
||||
);
|
||||
|
@ -725,18 +729,18 @@ class FlutterVmService {
|
|||
/// If a non-null value is provided for [platform], the platform override
|
||||
/// is updated with this value.
|
||||
Future<String> flutterPlatformOverride({
|
||||
String platform,
|
||||
@required String isolateId,
|
||||
String? platform,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? result = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.platformOverride',
|
||||
isolateId: isolateId,
|
||||
args: platform != null
|
||||
? <String, dynamic>{'value': platform}
|
||||
? <String, Object>{'value': platform}
|
||||
: <String, String>{},
|
||||
);
|
||||
if (result != null && result['value'] is String) {
|
||||
return result['value'] as String;
|
||||
return result['value']! as String;
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
|
@ -746,15 +750,15 @@ class FlutterVmService {
|
|||
///
|
||||
/// If a non-null value is provided for [brightness], the brightness override
|
||||
/// is updated with this value.
|
||||
Future<Brightness> flutterBrightnessOverride({
|
||||
Brightness brightness,
|
||||
@required String isolateId,
|
||||
Future<Brightness?> flutterBrightnessOverride({
|
||||
Brightness? brightness,
|
||||
required String isolateId,
|
||||
}) async {
|
||||
final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw(
|
||||
final Map<String, Object?>? result = await invokeFlutterExtensionRpcRaw(
|
||||
'ext.flutter.brightnessOverride',
|
||||
isolateId: isolateId,
|
||||
args: brightness != null
|
||||
? <String, dynamic>{'value': brightness.toString()}
|
||||
? <String, String>{'value': brightness.toString()}
|
||||
: <String, String>{},
|
||||
);
|
||||
if (result != null && result['value'] is String) {
|
||||
|
@ -765,9 +769,9 @@ class FlutterVmService {
|
|||
return null;
|
||||
}
|
||||
|
||||
Future<vm_service.Response> _checkedCallServiceExtension(
|
||||
Future<vm_service.Response?> _checkedCallServiceExtension(
|
||||
String method, {
|
||||
Map<String, dynamic> args,
|
||||
Map<String, Object?>? args,
|
||||
}) async {
|
||||
try {
|
||||
return await service.callServiceExtension(method, args: args);
|
||||
|
@ -784,14 +788,14 @@ class FlutterVmService {
|
|||
|
||||
/// Invoke a flutter extension method, if the flutter extension is not
|
||||
/// available, returns null.
|
||||
Future<Map<String, dynamic>> invokeFlutterExtensionRpcRaw(
|
||||
Future<Map<String, Object?>?> invokeFlutterExtensionRpcRaw(
|
||||
String method, {
|
||||
@required String isolateId,
|
||||
Map<String, dynamic> args,
|
||||
required String isolateId,
|
||||
Map<String, Object?>? args,
|
||||
}) async {
|
||||
final vm_service.Response response = await _checkedCallServiceExtension(
|
||||
final vm_service.Response? response = await _checkedCallServiceExtension(
|
||||
method,
|
||||
args: <String, Object>{
|
||||
args: <String, Object?>{
|
||||
'isolateId': isolateId,
|
||||
...?args,
|
||||
},
|
||||
|
@ -810,7 +814,7 @@ class FlutterVmService {
|
|||
Duration delay = const Duration(milliseconds: 50),
|
||||
}) async {
|
||||
while (true) {
|
||||
final vm_service.Response response = await callMethodWrapper(
|
||||
final vm_service.Response? response = await callMethodWrapper(
|
||||
kListViewsMethod,
|
||||
);
|
||||
if (response == null) {
|
||||
|
@ -819,7 +823,7 @@ class FlutterVmService {
|
|||
// with cleaning up.
|
||||
return <FlutterView>[];
|
||||
}
|
||||
final List<Object> rawViews = response.json['views'] as List<Object>;
|
||||
final List<Object>? rawViews = response.json?['views'] as List<Object>?;
|
||||
final List<FlutterView> views = <FlutterView>[
|
||||
if (rawViews != null)
|
||||
for (final Object rawView in rawViews)
|
||||
|
@ -850,11 +854,11 @@ class FlutterVmService {
|
|||
}
|
||||
|
||||
final Completer<vm_service.IsolateRef> extensionAdded = Completer<vm_service.IsolateRef>();
|
||||
StreamSubscription<vm_service.Event> isolateEvents;
|
||||
late final StreamSubscription<vm_service.Event> isolateEvents;
|
||||
isolateEvents = service.onIsolateEvent.listen((vm_service.Event event) {
|
||||
if (event.kind == vm_service.EventKind.kServiceExtensionAdded
|
||||
&& event.extensionRPC == extensionName) {
|
||||
isolateEvents?.cancel();
|
||||
isolateEvents.cancel();
|
||||
extensionAdded.complete(event.isolate);
|
||||
}
|
||||
});
|
||||
|
@ -862,7 +866,7 @@ class FlutterVmService {
|
|||
try {
|
||||
final List<vm_service.IsolateRef> refs = await _getIsolateRefs();
|
||||
for (final vm_service.IsolateRef ref in refs) {
|
||||
final vm_service.Isolate isolate = await getIsolateOrNull(ref.id);
|
||||
final vm_service.Isolate? isolate = await getIsolateOrNull(ref.id!);
|
||||
if (isolate != null && isolate.extensionRPCs?.contains(extensionName) == true) {
|
||||
return ref;
|
||||
}
|
||||
|
@ -886,7 +890,7 @@ class FlutterVmService {
|
|||
|
||||
final List<vm_service.IsolateRef> refs = <vm_service.IsolateRef>[];
|
||||
for (final FlutterView flutterView in flutterViews) {
|
||||
final vm_service.IsolateRef uiIsolate = flutterView.uiIsolate;
|
||||
final vm_service.IsolateRef? uiIsolate = flutterView.uiIsolate;
|
||||
if (uiIsolate != null) {
|
||||
refs.add(uiIsolate);
|
||||
}
|
||||
|
@ -896,11 +900,13 @@ class FlutterVmService {
|
|||
|
||||
/// Attempt to retrieve the isolate with id [isolateId], or `null` if it has
|
||||
/// been collected.
|
||||
Future<vm_service.Isolate> getIsolateOrNull(String isolateId) async {
|
||||
Future<vm_service.Isolate?> getIsolateOrNull(String isolateId) async {
|
||||
return service.getIsolate(isolateId)
|
||||
.catchError((dynamic error, StackTrace stackTrace) {
|
||||
// The .then() call is required to cast from Future<Isolate> to Future<Isolate?>
|
||||
.then<vm_service.Isolate?>((vm_service.Isolate isolate) => isolate)
|
||||
.catchError((Object? error, StackTrace stackTrace) {
|
||||
return null;
|
||||
}, test: (dynamic error) {
|
||||
}, test: (Object? error) {
|
||||
return (error is vm_service.SentinelException) ||
|
||||
(error is vm_service.RPCError && error.code == RPCErrorCodes.kServiceDisappeared);
|
||||
});
|
||||
|
@ -912,7 +918,7 @@ class FlutterVmService {
|
|||
// has custom handling of certain RPCErrors.
|
||||
return service.callServiceExtension(
|
||||
'_createDevFS',
|
||||
args: <String, dynamic>{'fsName': fsName},
|
||||
args: <String, Object?>{'fsName': fsName},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -920,15 +926,15 @@ class FlutterVmService {
|
|||
Future<void> deleteDevFS(String fsName) async {
|
||||
await _checkedCallServiceExtension(
|
||||
'_deleteDevFS',
|
||||
args: <String, dynamic>{'fsName': fsName},
|
||||
args: <String, Object?>{'fsName': fsName},
|
||||
);
|
||||
}
|
||||
|
||||
Future<vm_service.Response> screenshot() {
|
||||
Future<vm_service.Response?> screenshot() {
|
||||
return _checkedCallServiceExtension(kScreenshotMethod);
|
||||
}
|
||||
|
||||
Future<vm_service.Response> screenshotSkp() {
|
||||
Future<vm_service.Response?> screenshotSkp() {
|
||||
return _checkedCallServiceExtension(kScreenshotSkpMethod);
|
||||
}
|
||||
|
||||
|
@ -937,13 +943,13 @@ class FlutterVmService {
|
|||
assert(recordedStreams != null);
|
||||
await _checkedCallServiceExtension(
|
||||
'setVMTimelineFlags',
|
||||
args: <String, dynamic>{
|
||||
args: <String, Object?>{
|
||||
'recordedStreams': recordedStreams,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<vm_service.Response> getTimeline() {
|
||||
Future<vm_service.Response?> getTimeline() {
|
||||
return _checkedCallServiceExtension('getVMTimeline');
|
||||
}
|
||||
|
||||
|
@ -985,7 +991,7 @@ enum Brightness {
|
|||
|
||||
/// Process a VM service log event into a string message.
|
||||
String processVmServiceMessage(vm_service.Event event) {
|
||||
final String message = utf8.decode(base64.decode(event.bytes));
|
||||
final String message = utf8.decode(base64.decode(event.bytes!));
|
||||
// Remove extra trailing newlines appended by the vm service.
|
||||
if (message.endsWith('\n')) {
|
||||
return message.substring(0, message.length - 1);
|
||||
|
|
|
@ -481,7 +481,7 @@ void main() {
|
|||
});
|
||||
|
||||
testWithoutContext('computeDartVmFlags handles various combinations of Dart VM flags and null_assertions', () {
|
||||
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: null)), '');
|
||||
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug)), '');
|
||||
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: '--foo')), '--foo');
|
||||
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: '', nullAssertions: true)), '--null_assertions');
|
||||
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: '--foo', nullAssertions: true)), '--foo,--null_assertions');
|
||||
|
|
|
@ -796,7 +796,7 @@ void main() {
|
|||
},
|
||||
),
|
||||
]);
|
||||
final FakeDelegateFlutterDevice flutterDevice = FakeDelegateFlutterDevice(
|
||||
final FakeDelegateFlutterDevice flutterDevice = FakeDelegateFlutterDevice(
|
||||
device,
|
||||
BuildInfo.debug,
|
||||
FakeResidentCompiler(),
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:test_api/test_api.dart' hide test; // ignore: deprecated_member_use
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
|
@ -19,9 +16,9 @@ export 'package:test_api/test_api.dart' hide test, isInstanceOf; // ignore: depr
|
|||
/// and response structure.
|
||||
class FakeVmServiceHost {
|
||||
FakeVmServiceHost({
|
||||
@required List<VmServiceExpectation> requests,
|
||||
Uri httpAddress,
|
||||
Uri wsAddress,
|
||||
required List<VmServiceExpectation> requests,
|
||||
Uri? httpAddress,
|
||||
Uri? wsAddress,
|
||||
}) : _requests = requests {
|
||||
_vmService = FlutterVmService(vm_service.VmService(
|
||||
_input.stream,
|
||||
|
@ -44,16 +41,16 @@ class FakeVmServiceHost {
|
|||
return;
|
||||
}
|
||||
if (fakeRequest.errorCode == null) {
|
||||
_input.add(json.encode(<String, Object>{
|
||||
_input.add(json.encode(<String, Object?>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': request['id'],
|
||||
'result': fakeRequest.jsonResponse ?? <String, Object>{'type': 'Success'},
|
||||
}));
|
||||
} else {
|
||||
_input.add(json.encode(<String, Object>{
|
||||
_input.add(json.encode(<String, Object?>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': request['id'],
|
||||
'error': <String, Object>{
|
||||
'error': <String, Object?>{
|
||||
'code': fakeRequest.errorCode,
|
||||
}
|
||||
}));
|
||||
|
@ -67,7 +64,7 @@ class FakeVmServiceHost {
|
|||
final StreamController<String> _output = StreamController<String>();
|
||||
|
||||
FlutterVmService get vmService => _vmService;
|
||||
FlutterVmService _vmService;
|
||||
late final FlutterVmService _vmService;
|
||||
|
||||
|
||||
bool get hasRemainingExpectations => _requests.isNotEmpty;
|
||||
|
@ -95,7 +92,7 @@ abstract class VmServiceExpectation {
|
|||
|
||||
class FakeVmServiceRequest implements VmServiceExpectation {
|
||||
const FakeVmServiceRequest({
|
||||
@required this.method,
|
||||
required this.method,
|
||||
this.args = const <String, Object>{},
|
||||
this.jsonResponse,
|
||||
this.errorCode,
|
||||
|
@ -109,9 +106,9 @@ class FakeVmServiceRequest implements VmServiceExpectation {
|
|||
|
||||
/// If non-null, the error code for a [vm_service.RPCError] in place of a
|
||||
/// standard response.
|
||||
final int errorCode;
|
||||
final Map<String, Object> args;
|
||||
final Map<String, Object> jsonResponse;
|
||||
final int? errorCode;
|
||||
final Map<String, Object>? args;
|
||||
final Map<String, Object>? jsonResponse;
|
||||
|
||||
@override
|
||||
bool get isRequest => true;
|
||||
|
@ -119,8 +116,8 @@ class FakeVmServiceRequest implements VmServiceExpectation {
|
|||
|
||||
class FakeVmServiceStreamResponse implements VmServiceExpectation {
|
||||
const FakeVmServiceStreamResponse({
|
||||
@required this.event,
|
||||
@required this.streamId,
|
||||
required this.event,
|
||||
required this.streamId,
|
||||
});
|
||||
|
||||
final vm_service.Event event;
|
||||
|
|
Loading…
Reference in a new issue