Skip to content

Commit 94550c6

Browse files
authored
prevent tool crash when IntelliJValidatorOnMac encounters an installation with a missing CFBundleIdentifier (flutter#138095)
Fixes flutter#138029 (see my comment there for more info)
1 parent 2f62af4 commit 94550c6

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

packages/flutter_tools/lib/src/doctor.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,20 @@ abstract class DoctorValidatorsProvider {
5353
// [FeatureFlags].
5454
factory DoctorValidatorsProvider.test({
5555
Platform? platform,
56+
Logger? logger,
5657
required FeatureFlags featureFlags,
5758
}) {
5859
return _DefaultDoctorValidatorsProvider(
5960
featureFlags: featureFlags,
6061
platform: platform ?? FakePlatform(),
62+
logger: logger ?? BufferLogger.test(),
6163
);
6264
}
6365
/// The singleton instance, pulled from the [AppContext].
6466
static DoctorValidatorsProvider get _instance => context.get<DoctorValidatorsProvider>()!;
6567

6668
static final DoctorValidatorsProvider defaultInstance = _DefaultDoctorValidatorsProvider(
69+
logger: globals.logger,
6770
platform: globals.platform,
6871
featureFlags: featureFlags,
6972
);
@@ -76,12 +79,14 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
7679
_DefaultDoctorValidatorsProvider({
7780
required this.platform,
7881
required this.featureFlags,
79-
});
82+
required Logger logger,
83+
}) : _logger = logger;
8084

8185
List<DoctorValidator>? _validators;
8286
List<Workflow>? _workflows;
8387
final Platform platform;
8488
final FeatureFlags featureFlags;
89+
final Logger _logger;
8590

8691
late final LinuxWorkflow linuxWorkflow = LinuxWorkflow(
8792
platform: platform,
@@ -117,6 +122,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
117122
userMessages: userMessages,
118123
plistParser: globals.plistParser,
119124
processManager: globals.processManager,
125+
logger: _logger,
120126
),
121127
...VsCodeValidator.installedValidators(globals.fs, platform, globals.processManager),
122128
];

packages/flutter_tools/lib/src/intellij/intellij_validator.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:process/process.dart';
77

88
import '../base/file_system.dart';
99
import '../base/io.dart';
10+
import '../base/logger.dart';
1011
import '../base/platform.dart';
1112
import '../base/user_messages.dart' hide userMessages;
1213
import '../base/version.dart';
@@ -50,6 +51,7 @@ abstract class IntelliJValidator extends DoctorValidator {
5051
static Iterable<DoctorValidator> installedValidators({
5152
required FileSystem fileSystem,
5253
required Platform platform,
54+
required Logger logger,
5355
required UserMessages userMessages,
5456
required PlistParser plistParser,
5557
required ProcessManager processManager,
@@ -77,6 +79,7 @@ abstract class IntelliJValidator extends DoctorValidator {
7779
userMessages: userMessages,
7880
plistParser: plistParser,
7981
processManager: processManager,
82+
logger: logger,
8083
);
8184
}
8285
return <DoctorValidator>[];
@@ -364,6 +367,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
364367
required UserMessages userMessages,
365368
required PlistParser plistParser,
366369
required String? homeDirPath,
370+
367371
}) : _plistParser = plistParser,
368372
_homeDirPath = homeDirPath,
369373
super(title, installPath, fileSystem: fileSystem, userMessages: userMessages);
@@ -382,6 +386,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
382386
static Iterable<DoctorValidator> installed({
383387
required FileSystem fileSystem,
384388
required FileSystemUtils fileSystemUtils,
389+
required Logger logger,
385390
required UserMessages userMessages,
386391
required PlistParser plistParser,
387392
required ProcessManager processManager,
@@ -490,10 +495,16 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
490495
if (validator is! IntelliJValidatorOnMac) {
491496
return false;
492497
}
493-
final String identifierKey = plistParser.getValueFromFile(
498+
final String? identifierKey = plistParser.getValueFromFile<String>(
494499
validator.plistFile,
495500
PlistParser.kCFBundleIdentifierKey,
496-
) as String;
501+
);
502+
if (identifierKey == null) {
503+
logger.printTrace('Android Studio/IntelliJ installation at '
504+
'${validator.installPath} has a null CFBundleIdentifierKey, '
505+
'which is a required field.');
506+
return false;
507+
}
497508
return identifierKey.contains('com.jetbrains.toolbox.linkapp');
498509
});
499510

packages/flutter_tools/test/general.shard/intellij/intellij_validator_test.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:archive/archive.dart';
66
import 'package:file/memory.dart';
77
import 'package:flutter_tools/src/base/file_system.dart';
8+
import 'package:flutter_tools/src/base/logger.dart';
89
import 'package:flutter_tools/src/base/platform.dart';
910
import 'package:flutter_tools/src/base/user_messages.dart';
1011
import 'package:flutter_tools/src/convert.dart';
@@ -308,6 +309,7 @@ void main() {
308309
PlistParser.kCFBundleShortVersionStringKey: '2020.10',
309310
PlistParser.kCFBundleIdentifierKey: 'com.jetbrains.intellij',
310311
}),
312+
logger: BufferLogger.test(),
311313
).whereType<IntelliJValidatorOnMac>();
312314
expect(validators.length, 2);
313315

@@ -389,6 +391,7 @@ void main() {
389391
'CFBundleIdentifier': 'com.jetbrains.toolbox.linkapp',
390392
}),
391393
processManager: processManager,
394+
logger: BufferLogger.test(),
392395
);
393396

394397
expect(validators.length, 1);
@@ -431,11 +434,56 @@ void main() {
431434
'CFBundleIdentifier': 'com.jetbrains.toolbox.linkapp',
432435
}),
433436
processManager: processManager,
437+
logger: BufferLogger.test(),
434438
);
435439

436440
expect(installed.length, 0);
437441
expect(processManager, hasNoRemainingExpectations);
438442
});
443+
444+
testWithoutContext('Does not crash when installation is missing its CFBundleIdentifier property', () async {
445+
final BufferLogger logger = BufferLogger.test();
446+
final FileSystem fileSystem = MemoryFileSystem.test();
447+
final String ultimatePath = fileSystem.path.join('/', 'foo', 'bar', 'Applications',
448+
'JetBrains Toolbox', 'IntelliJ IDEA Ultimate.app');
449+
final String communityEditionPath = fileSystem.path.join('/', 'foo', 'bar', 'Applications',
450+
'JetBrains Toolbox', 'IntelliJ IDEA Community Edition.app');
451+
final List<String> installPaths = <String>[
452+
ultimatePath,
453+
communityEditionPath
454+
];
455+
456+
for (final String installPath in installPaths) {
457+
fileSystem.directory(installPath).createSync(recursive: true);
458+
}
459+
460+
final FakeProcessManager processManager =
461+
FakeProcessManager.list(<FakeCommand>[
462+
FakeCommand(command: const <String>[
463+
'mdfind',
464+
'kMDItemCFBundleIdentifier="com.jetbrains.intellij.ce"',
465+
], stdout: communityEditionPath),
466+
FakeCommand(command: const <String>[
467+
'mdfind',
468+
'kMDItemCFBundleIdentifier="com.jetbrains.intellij*"',
469+
], stdout: ultimatePath)
470+
]);
471+
472+
final Iterable<DoctorValidator> installed = IntelliJValidatorOnMac.installed(
473+
fileSystem: fileSystem,
474+
fileSystemUtils: FileSystemUtils(fileSystem: fileSystem, platform: macPlatform),
475+
userMessages: UserMessages(),
476+
plistParser: FakePlistParser(<String, String>{
477+
'JetBrainsToolboxApp': '/path/to/JetBrainsToolboxApp',
478+
}),
479+
processManager: processManager,
480+
logger: logger,
481+
);
482+
483+
expect(installed.length, 2);
484+
expect(logger.traceText, contains('installation at $ultimatePath has a null CFBundleIdentifierKey'));
485+
expect(processManager, hasNoRemainingExpectations);
486+
});
439487
}
440488

441489
class IntelliJValidatorTestTarget extends IntelliJValidator {

0 commit comments

Comments
 (0)