[flutter_tools] Fix TypeError when a FileSystemException happens during flutter doctor (#133373)
Fixes https://github.com/flutter/flutter/issues/133086
diff --git a/packages/flutter_tools/lib/src/intellij/intellij_validator.dart b/packages/flutter_tools/lib/src/intellij/intellij_validator.dart
index 691d8e5..4b2b436 100644
--- a/packages/flutter_tools/lib/src/intellij/intellij_validator.dart
+++ b/packages/flutter_tools/lib/src/intellij/intellij_validator.dart
@@ -487,8 +487,11 @@
// Remove JetBrains Toolbox link apps. These tiny apps just
// link to the full app, will get detected elsewhere in our search.
validators.removeWhere((DoctorValidator validator) {
+ if (validator is! IntelliJValidatorOnMac) {
+ return false;
+ }
final String identifierKey = plistParser.getValueFromFile(
- (validator as IntelliJValidatorOnMac).plistFile,
+ validator.plistFile,
PlistParser.kCFBundleIdentifierKey,
) as String;
return identifierKey.contains('com.jetbrains.toolbox.linkapp');
diff --git a/packages/flutter_tools/test/general.shard/android/android_studio_test.dart b/packages/flutter_tools/test/general.shard/android/android_studio_test.dart
index cc8d8c2..2fca60b 100644
--- a/packages/flutter_tools/test/general.shard/android/android_studio_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_studio_test.dart
@@ -11,7 +11,6 @@
import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/ios/plist_parser.dart';
-import 'package:path/path.dart' show Context; // flutter_ignore: package_path_import -- We only use Context as an interface.
import 'package:test/fake.dart';
import '../../src/common.dart';
diff --git a/packages/flutter_tools/test/general.shard/base/error_handling_io_test.dart b/packages/flutter_tools/test/general.shard/base/error_handling_io_test.dart
index f9fa8ef..e6363ce 100644
--- a/packages/flutter_tools/test/general.shard/base/error_handling_io_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/error_handling_io_test.dart
@@ -12,7 +12,6 @@
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
-import 'package:path/path.dart' as p; // flutter_ignore: package_path_import
import 'package:process/process.dart';
import 'package:test/fake.dart';
@@ -1293,7 +1292,7 @@
class FakeFileSystem extends Fake implements FileSystem {
@override
- p.Context get path => p.Context();
+ Context get path => Context();
@override
Directory get currentDirectory {
diff --git a/packages/flutter_tools/test/general.shard/intellij/intellij_validator_test.dart b/packages/flutter_tools/test/general.shard/intellij/intellij_validator_test.dart
index bd7f810..f2bc787 100644
--- a/packages/flutter_tools/test/general.shard/intellij/intellij_validator_test.dart
+++ b/packages/flutter_tools/test/general.shard/intellij/intellij_validator_test.dart
@@ -11,6 +11,7 @@
import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:flutter_tools/src/intellij/intellij_validator.dart';
import 'package:flutter_tools/src/ios/plist_parser.dart';
+import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/fake_process_manager.dart';
@@ -373,6 +374,29 @@
expect(validator.pluginsPath, '/path/to/JetBrainsToolboxApp.plugins');
});
+ testWithoutContext('IntelliJValidatorOnMac.installed() handles FileSystemExceptions)', () async {
+ const FileSystemException exception = FileSystemException('cannot list');
+ final FileSystem fileSystem = _ThrowingFileSystem(exception);
+
+ final FakeProcessManager processManager = FakeProcessManager.empty();
+
+ final Iterable<DoctorValidator> validators = IntelliJValidatorOnMac.installed(
+ fileSystem: fileSystem,
+ fileSystemUtils: FileSystemUtils(fileSystem: fileSystem, platform: macPlatform),
+ userMessages: UserMessages(),
+ plistParser: FakePlistParser(<String, String>{
+ 'JetBrainsToolboxApp': '/path/to/JetBrainsToolboxApp',
+ 'CFBundleIdentifier': 'com.jetbrains.toolbox.linkapp',
+ }),
+ processManager: processManager,
+ );
+
+ expect(validators.length, 1);
+ final DoctorValidator validator = validators.first;
+ expect(validator, isA<ValidatorWithResult>());
+ expect(validator.title, 'Cannot determine if IntelliJ is installed');
+ });
+
testWithoutContext('Remove JetBrains Toolbox', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final List<String> installPaths = <String>[
@@ -398,11 +422,9 @@
], stdout: 'skip')
]);
- final Iterable<DoctorValidator> installed =
- IntelliJValidatorOnMac.installed(
+ final Iterable<DoctorValidator> installed = IntelliJValidatorOnMac.installed(
fileSystem: fileSystem,
- fileSystemUtils:
- FileSystemUtils(fileSystem: fileSystem, platform: macPlatform),
+ fileSystemUtils: FileSystemUtils(fileSystem: fileSystem, platform: macPlatform),
userMessages: UserMessages(),
plistParser: FakePlistParser(<String, String>{
'JetBrainsToolboxApp': '/path/to/JetBrainsToolboxApp',
@@ -412,6 +434,7 @@
);
expect(installed.length, 0);
+ expect(processManager, hasNoRemainingExpectations);
});
}
@@ -458,7 +481,6 @@
fileSystem.file(pluginJarPath)
..createSync(recursive: true)
..writeAsBytesSync(ZipEncoder().encode(flutterPlugins)!);
-
}
/// A helper to create a Intellij Dart plugin jar.
@@ -496,3 +518,30 @@
..createSync(recursive: true)
..writeAsBytesSync(ZipEncoder().encode(dartPlugins)!);
}
+
+// TODO(fujino): this should use the MemoryFileSystem and a
+// FileExceptionHandler, blocked by https://github.com/google/file.dart/issues/227.
+class _ThrowingFileSystem extends Fake implements FileSystem {
+ _ThrowingFileSystem(this._exception);
+
+ final Exception _exception;
+ final MemoryFileSystem memfs = MemoryFileSystem.test();
+
+ @override
+ Context get path => memfs.path;
+
+ @override
+ Directory directory(dynamic _) => _ThrowingDirectory(_exception);
+}
+
+class _ThrowingDirectory extends Fake implements Directory {
+ _ThrowingDirectory(this._exception);
+
+ final Exception _exception;
+
+ @override
+ bool existsSync() => true;
+
+ @override
+ List<FileSystemEntity> listSync({bool recursive = false, bool followLinks = true}) => throw _exception;
+}
diff --git a/packages/flutter_tools/test/general.shard/xcode_backend_test.dart b/packages/flutter_tools/test/general.shard/xcode_backend_test.dart
index 482e4ed..dd36810 100644
--- a/packages/flutter_tools/test/general.shard/xcode_backend_test.dart
+++ b/packages/flutter_tools/test/general.shard/xcode_backend_test.dart
@@ -7,7 +7,7 @@
import 'package:flutter_tools/src/base/io.dart';
import '../../bin/xcode_backend.dart';
-import '../src/common.dart';
+import '../src/common.dart' hide Context;
import '../src/fake_process_manager.dart';
void main() {
diff --git a/packages/flutter_tools/test/src/common.dart b/packages/flutter_tools/test/src/common.dart
index e97fb95..ca005f2 100644
--- a/packages/flutter_tools/test/src/common.dart
+++ b/packages/flutter_tools/test/src/common.dart
@@ -17,6 +17,7 @@
import 'package:test/test.dart' as test_package show test;
import 'package:test/test.dart' hide test;
+export 'package:path/path.dart' show Context; // flutter_ignore: package_path_import
export 'package:test/test.dart' hide isInstanceOf, test;
void tryToDelete(FileSystemEntity fileEntity) {