Unverified Commit cba84d51 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove globals from IntelliJ validator, refactor tests to...

[flutter_tools] remove globals from IntelliJ validator, refactor tests to remove dependency on JAR (#67240)

Move the intellij validator to its own file, and split off the tests. Remove globals from each, and remove dependency on a real jar/filesystem by creating a minimal version of the manifest xml and setting it up in the memory file system.

#47161
parent e53bb746
......@@ -17,14 +17,12 @@ import 'base/platform.dart';
import 'base/terminal.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
import 'base/version.dart';
import 'cache.dart';
import 'device.dart';
import 'features.dart';
import 'fuchsia/fuchsia_workflow.dart';
import 'globals.dart' as globals;
import 'intellij/intellij.dart';
import 'ios/plist_parser.dart';
import 'intellij/intellij_validator.dart';
import 'linux/linux_doctor.dart';
import 'linux/linux_workflow.dart';
import 'macos/macos_workflow.dart';
......@@ -77,7 +75,12 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
final List<DoctorValidator> ideValidators = <DoctorValidator>[
...AndroidStudioValidator.allValidators(globals.config, globals.platform, globals.fs, globals.userMessages),
...IntelliJValidator.installedValidators(globals.fs, globals.platform),
...IntelliJValidator.installedValidators(
fileSystem: globals.fs,
platform: globals.platform,
userMessages: userMessages,
plistParser: globals.plistParser,
),
...VsCodeValidator.installedValidators(globals.fs, globals.platform),
];
final ProxyValidator proxyValidator = ProxyValidator(platform: globals.platform);
......@@ -774,272 +777,6 @@ class NoIdeValidator extends DoctorValidator {
}
}
/// A doctor validator for both Intellij and Android Studio.
abstract class IntelliJValidator extends DoctorValidator {
IntelliJValidator(String title, this.installPath, {
@required FileSystem fileSystem,
}) : _fileSystem = fileSystem,
super(title);
final String installPath;
final FileSystem _fileSystem;
String get version;
String get pluginsPath;
static final Map<String, String> _idToTitle = <String, String>{
'IntelliJIdea': 'IntelliJ IDEA Ultimate Edition',
'IdeaIC': 'IntelliJ IDEA Community Edition',
};
static final Version kMinIdeaVersion = Version(2017, 1, 0);
static Iterable<DoctorValidator> installedValidators(FileSystem fileSystem, Platform platform) {
if (platform.isLinux || platform.isWindows) {
return IntelliJValidatorOnLinuxAndWindows.installed(fileSystem);
}
if (platform.isMacOS) {
return IntelliJValidatorOnMac.installed(fileSystem);
}
return <DoctorValidator>[];
}
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
if (pluginsPath == null) {
messages.add(const ValidationMessage.error('Invalid IntelliJ version number.'));
} else {
messages.add(ValidationMessage(userMessages.intellijLocation(installPath)));
final IntelliJPlugins plugins = IntelliJPlugins(pluginsPath, fileSystem: _fileSystem);
plugins.validatePackage(
messages,
<String>['flutter-intellij', 'flutter-intellij.jar'],
'Flutter',
IntelliJPlugins.kIntellijFlutterPluginUrl,
minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
);
plugins.validatePackage(
messages,
<String>['Dart'],
'Dart',
IntelliJPlugins.kIntellijDartPluginUrl,
);
if (_hasIssues(messages)) {
messages.add(ValidationMessage(userMessages.intellijPluginInfo));
}
_validateIntelliJVersion(messages, kMinIdeaVersion);
}
return ValidationResult(
_hasIssues(messages) ? ValidationType.partial : ValidationType.installed,
messages,
statusInfo: userMessages.intellijStatusInfo(version),
);
}
bool _hasIssues(List<ValidationMessage> messages) {
return messages.any((ValidationMessage message) => message.isError);
}
void _validateIntelliJVersion(List<ValidationMessage> messages, Version minVersion) {
// Ignore unknown versions.
if (minVersion == Version.unknown) {
return;
}
final Version installedVersion = Version.parse(version);
if (installedVersion == null) {
return;
}
if (installedVersion < minVersion) {
messages.add(ValidationMessage.error(userMessages.intellijMinimumVersion(minVersion.toString())));
}
}
}
/// A linux and windows specific implementation of the intellij validator.
class IntelliJValidatorOnLinuxAndWindows extends IntelliJValidator {
IntelliJValidatorOnLinuxAndWindows(String title, this.version, String installPath, this.pluginsPath, {
@required FileSystem fileSystem,
}) : super(title, installPath, fileSystem: fileSystem);
@override
final String version;
@override
final String pluginsPath;
static Iterable<DoctorValidator> installed(FileSystem fileSystem) {
final List<DoctorValidator> validators = <DoctorValidator>[];
if (globals.fsUtils.homeDirPath == null) {
return validators;
}
void addValidator(String title, String version, String installPath, String pluginsPath) {
final IntelliJValidatorOnLinuxAndWindows validator =
IntelliJValidatorOnLinuxAndWindows(title, version, installPath, pluginsPath, fileSystem: fileSystem);
for (int index = 0; index < validators.length; ++index) {
final DoctorValidator other = validators[index];
if (other is IntelliJValidatorOnLinuxAndWindows && validator.installPath == other.installPath) {
if (validator.version.compareTo(other.version) > 0) {
validators[index] = validator;
}
return;
}
}
validators.add(validator);
}
final Directory homeDir = globals.fs.directory(globals.fsUtils.homeDirPath);
for (final Directory dir in homeDir.listSync().whereType<Directory>()) {
final String name = globals.fs.path.basename(dir.path);
IntelliJValidator._idToTitle.forEach((String id, String title) {
if (name.startsWith('.$id')) {
final String version = name.substring(id.length + 1);
String installPath;
try {
installPath = globals.fs.file(globals.fs.path.join(dir.path, 'system', '.home')).readAsStringSync();
} on Exception {
// ignored
}
if (installPath != null && globals.fs.isDirectorySync(installPath)) {
final String pluginsPath = globals.fs.path.join(dir.path, 'config', 'plugins');
addValidator(title, version, installPath, pluginsPath);
}
}
});
}
return validators;
}
}
/// A macOS specific implementation of the intellij validator.
class IntelliJValidatorOnMac extends IntelliJValidator {
IntelliJValidatorOnMac(String title, this.id, String installPath, {
@required FileSystem fileSystem,
}) : super(title, installPath, fileSystem: fileSystem);
final String id;
static final Map<String, String> _dirNameToId = <String, String>{
'IntelliJ IDEA.app': 'IntelliJIdea',
'IntelliJ IDEA Ultimate.app': 'IntelliJIdea',
'IntelliJ IDEA CE.app': 'IdeaIC',
};
static Iterable<DoctorValidator> installed(FileSystem fileSystem) {
final List<DoctorValidator> validators = <DoctorValidator>[];
final List<String> installPaths = <String>[
'/Applications',
fileSystem.path.join(globals.fsUtils.homeDirPath, 'Applications'),
];
void checkForIntelliJ(Directory dir) {
final String name = fileSystem.path.basename(dir.path);
_dirNameToId.forEach((String dirName, String id) {
if (name == dirName) {
final String title = IntelliJValidator._idToTitle[id];
validators.add(IntelliJValidatorOnMac(title, id, dir.path, fileSystem: fileSystem));
}
});
}
try {
final Iterable<Directory> installDirs = installPaths
.map(fileSystem.directory)
.map<List<FileSystemEntity>>((Directory dir) => dir.existsSync() ? dir.listSync() : <FileSystemEntity>[])
.expand<FileSystemEntity>((List<FileSystemEntity> mappedDirs) => mappedDirs)
.whereType<Directory>();
for (final Directory dir in installDirs) {
checkForIntelliJ(dir);
if (!dir.path.endsWith('.app')) {
for (final FileSystemEntity subdir in dir.listSync()) {
if (subdir is Directory) {
checkForIntelliJ(subdir);
}
}
}
}
} on FileSystemException catch (e) {
validators.add(ValidatorWithResult(
userMessages.intellijMacUnknownResult,
ValidationResult(ValidationType.missing, <ValidationMessage>[
ValidationMessage.error(e.message),
]),
));
}
return validators;
}
@visibleForTesting
String get plistFile {
_plistFile ??= _fileSystem.path.join(installPath, 'Contents', 'Info.plist');
return _plistFile;
}
String _plistFile;
@override
String get version {
_version ??= globals.plistParser.getValueFromFile(
plistFile,
PlistParser.kCFBundleShortVersionStringKey,
) ?? 'unknown';
return _version;
}
String _version;
@override
String get pluginsPath {
if (_pluginsPath != null) {
return _pluginsPath;
}
final String altLocation = globals.plistParser
.getValueFromFile(plistFile, 'JetBrainsToolboxApp');
if (altLocation != null) {
_pluginsPath = altLocation + '.plugins';
return _pluginsPath;
}
final List<String> split = version.split('.');
if (split.length < 2) {
return null;
}
final String major = split[0];
final String minor = split[1];
final String homeDirPath = globals.fsUtils.homeDirPath;
String pluginsPath = globals.fs.path.join(
homeDirPath,
'Library',
'Application Support',
'JetBrains',
'$id$major.$minor',
'plugins',
);
// Fallback to legacy location from < 2020.
if (!globals.fs.isDirectorySync(pluginsPath)) {
pluginsPath = globals.fs.path.join(
homeDirPath,
'Library',
'Application Support',
'$id$major.$minor',
);
}
_pluginsPath = pluginsPath;
return _pluginsPath;
}
String _pluginsPath;
}
class DeviceValidator extends DoctorValidator {
// TODO(jmagman): Make required once g3 rolls and is updated.
DeviceValidator({
......
......@@ -10,6 +10,14 @@ import '../base/version.dart';
import '../convert.dart';
import '../doctor.dart';
/// A parser for the Intellij and Android Studio plugin JAR files.
///
/// This searches on the provided plugin path for a JAR archive, then
/// unzips it to parse the META-INF/plugin.xml for version information.
///
/// See also:
/// * [IntellijValidator], the validator base class that uses this to check
/// plugin versions.
class IntelliJPlugins {
IntelliJPlugins(this.pluginsPath, {
@required FileSystem fileSystem
......@@ -74,7 +82,7 @@ class IntelliJPlugins {
final int start = content.indexOf(versionStartTag);
final int end = content.indexOf('</version>', start);
return content.substring(start + versionStartTag.length, end);
} on Exception {
} on ArchiveException {
return null;
}
}
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import '../base/file_system.dart';
import '../base/platform.dart';
import '../base/user_messages.dart' hide userMessages;
import '../base/version.dart';
import '../doctor.dart';
import '../ios/plist_parser.dart';
import 'intellij.dart';
/// A doctor validator for both Intellij and Android Studio.
abstract class IntelliJValidator extends DoctorValidator {
IntelliJValidator(String title, this.installPath, {
@required FileSystem fileSystem,
@required UserMessages userMessages,
}) : _fileSystem = fileSystem,
_userMessages = userMessages,
super(title);
final String installPath;
final FileSystem _fileSystem;
final UserMessages _userMessages;
String get version;
String get pluginsPath;
static const Map<String, String> _idToTitle = <String, String>{
'IntelliJIdea': 'IntelliJ IDEA Ultimate Edition',
'IdeaIC': 'IntelliJ IDEA Community Edition',
};
static final Version kMinIdeaVersion = Version(2017, 1, 0);
/// Create a [DoctorValidator] for each installation of Intellij.
///
/// On platforms other than macOS, Linux, and Windows this returns an
/// empty list.
static Iterable<DoctorValidator> installedValidators({
@required FileSystem fileSystem,
@required Platform platform,
@required UserMessages userMessages,
@required PlistParser plistParser,
}) {
final FileSystemUtils fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform);
if (platform.isLinux || platform.isWindows) {
return IntelliJValidatorOnLinuxAndWindows.installed(
fileSystem: fileSystem,
fileSystemUtils: fileSystemUtils,
userMessages: userMessages,
);
}
if (platform.isMacOS) {
return IntelliJValidatorOnMac.installed(
fileSystem: fileSystem,
fileSystemUtils: fileSystemUtils,
userMessages: userMessages,
plistParser: plistParser,
);
}
return <DoctorValidator>[];
}
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
if (pluginsPath == null) {
messages.add(const ValidationMessage.error('Invalid IntelliJ version number.'));
} else {
messages.add(ValidationMessage(_userMessages.intellijLocation(installPath)));
final IntelliJPlugins plugins = IntelliJPlugins(pluginsPath, fileSystem: _fileSystem);
plugins.validatePackage(
messages,
<String>['flutter-intellij', 'flutter-intellij.jar'],
'Flutter',
IntelliJPlugins.kIntellijFlutterPluginUrl,
minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
);
plugins.validatePackage(
messages,
<String>['Dart'],
'Dart',
IntelliJPlugins.kIntellijDartPluginUrl,
);
if (_hasIssues(messages)) {
messages.add(ValidationMessage(_userMessages.intellijPluginInfo));
}
_validateIntelliJVersion(messages, kMinIdeaVersion);
}
return ValidationResult(
_hasIssues(messages) ? ValidationType.partial : ValidationType.installed,
messages,
statusInfo: _userMessages.intellijStatusInfo(version),
);
}
bool _hasIssues(List<ValidationMessage> messages) {
return messages.any((ValidationMessage message) => message.isError);
}
void _validateIntelliJVersion(List<ValidationMessage> messages, Version minVersion) {
// Ignore unknown versions.
if (minVersion == Version.unknown) {
return;
}
final Version installedVersion = Version.parse(version);
if (installedVersion == null) {
return;
}
if (installedVersion < minVersion) {
messages.add(ValidationMessage.error(_userMessages.intellijMinimumVersion(minVersion.toString())));
}
}
}
/// A linux and windows specific implementation of the intellij validator.
class IntelliJValidatorOnLinuxAndWindows extends IntelliJValidator {
IntelliJValidatorOnLinuxAndWindows(String title, this.version, String installPath, this.pluginsPath, {
@required FileSystem fileSystem,
@required UserMessages userMessages,
}) : super(title, installPath, fileSystem: fileSystem, userMessages: userMessages);
@override
final String version;
@override
final String pluginsPath;
static Iterable<DoctorValidator> installed({
@required FileSystem fileSystem,
@required FileSystemUtils fileSystemUtils,
@required UserMessages userMessages,
}) {
final List<DoctorValidator> validators = <DoctorValidator>[];
if (fileSystemUtils.homeDirPath == null) {
return validators;
}
void addValidator(String title, String version, String installPath, String pluginsPath) {
final IntelliJValidatorOnLinuxAndWindows validator = IntelliJValidatorOnLinuxAndWindows(
title,
version,
installPath,
pluginsPath,
fileSystem: fileSystem,
userMessages: userMessages,
);
for (int index = 0; index < validators.length; index += 1) {
final DoctorValidator other = validators[index];
if (other is IntelliJValidatorOnLinuxAndWindows && validator.installPath == other.installPath) {
if (validator.version.compareTo(other.version) > 0) {
validators[index] = validator;
}
return;
}
}
validators.add(validator);
}
final Directory homeDir = fileSystem.directory(fileSystemUtils.homeDirPath);
for (final Directory dir in homeDir.listSync().whereType<Directory>()) {
final String name = fileSystem.path.basename(dir.path);
IntelliJValidator._idToTitle.forEach((String id, String title) {
if (name.startsWith('.$id')) {
final String version = name.substring(id.length + 1);
String installPath;
try {
installPath = fileSystem.file(fileSystem.path.join(dir.path, 'system', '.home')).readAsStringSync();
} on FileSystemException {
// ignored
}
if (installPath != null && fileSystem.isDirectorySync(installPath)) {
final String pluginsPath = fileSystem.path.join(dir.path, 'config', 'plugins');
addValidator(title, version, installPath, pluginsPath);
}
}
});
}
return validators;
}
}
/// A macOS specific implementation of the intellij validator.
class IntelliJValidatorOnMac extends IntelliJValidator {
IntelliJValidatorOnMac(String title, this.id, String installPath, {
@required FileSystem fileSystem,
@required UserMessages userMessages,
@required PlistParser plistParser,
@required String homeDirPath,
}) : _plistParser = plistParser,
_homeDirPath = homeDirPath,
super(title, installPath, fileSystem: fileSystem, userMessages: userMessages);
final String id;
final PlistParser _plistParser;
final String _homeDirPath;
static const Map<String, String> _dirNameToId = <String, String>{
'IntelliJ IDEA.app': 'IntelliJIdea',
'IntelliJ IDEA Ultimate.app': 'IntelliJIdea',
'IntelliJ IDEA CE.app': 'IdeaIC',
};
static Iterable<DoctorValidator> installed({
@required FileSystem fileSystem,
@required FileSystemUtils fileSystemUtils,
@required UserMessages userMessages,
@required PlistParser plistParser,
}) {
final List<DoctorValidator> validators = <DoctorValidator>[];
final List<String> installPaths = <String>[
'/Applications',
fileSystem.path.join(fileSystemUtils.homeDirPath, 'Applications'),
];
void checkForIntelliJ(Directory dir) {
final String name = fileSystem.path.basename(dir.path);
_dirNameToId.forEach((String dirName, String id) {
if (name == dirName) {
final String title = IntelliJValidator._idToTitle[id];
validators.add(IntelliJValidatorOnMac(
title,
id,
dir.path,
fileSystem: fileSystem,
userMessages: userMessages,
plistParser: plistParser,
homeDirPath: fileSystemUtils.homeDirPath,
));
}
});
}
try {
final Iterable<Directory> installDirs = installPaths
.map(fileSystem.directory)
.map<List<FileSystemEntity>>((Directory dir) => dir.existsSync() ? dir.listSync() : <FileSystemEntity>[])
.expand<FileSystemEntity>((List<FileSystemEntity> mappedDirs) => mappedDirs)
.whereType<Directory>();
for (final Directory dir in installDirs) {
checkForIntelliJ(dir);
if (!dir.path.endsWith('.app')) {
for (final FileSystemEntity subdir in dir.listSync()) {
if (subdir is Directory) {
checkForIntelliJ(subdir);
}
}
}
}
} on FileSystemException catch (e) {
validators.add(ValidatorWithResult(
userMessages.intellijMacUnknownResult,
ValidationResult(ValidationType.missing, <ValidationMessage>[
ValidationMessage.error(e.message),
]),
));
}
return validators;
}
@visibleForTesting
String get plistFile {
_plistFile ??= _fileSystem.path.join(installPath, 'Contents', 'Info.plist');
return _plistFile;
}
String _plistFile;
@override
String get version {
return _version ??= _plistParser.getValueFromFile(
plistFile,
PlistParser.kCFBundleShortVersionStringKey,
) ?? 'unknown';
}
String _version;
@override
String get pluginsPath {
if (_pluginsPath != null) {
return _pluginsPath;
}
final String altLocation = _plistParser
.getValueFromFile(plistFile, 'JetBrainsToolboxApp');
if (altLocation != null) {
_pluginsPath = altLocation + '.plugins';
return _pluginsPath;
}
final List<String> split = version.split('.');
if (split.length < 2) {
return null;
}
final String major = split[0];
final String minor = split[1];
final String homeDirPath = _homeDirPath;
String pluginsPath = _fileSystem.path.join(
homeDirPath,
'Library',
'Application Support',
'JetBrains',
'$id$major.$minor',
'plugins',
);
// Fallback to legacy location from < 2020.
if (!_fileSystem.isDirectorySync(pluginsPath)) {
pluginsPath = _fileSystem.path.join(
homeDirPath,
'Library',
'Application Support',
'$id$major.$minor',
);
}
_pluginsPath = pluginsPath;
return _pluginsPath;
}
String _pluginsPath;
}
......@@ -25,7 +25,6 @@ import 'package:flutter_tools/src/version.dart';
import 'package:flutter_tools/src/vscode/vscode.dart';
import 'package:flutter_tools/src/vscode/vscode_validator.dart';
import 'package:flutter_tools/src/web/workflow.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:fake_async/fake_async.dart';
......@@ -50,12 +49,10 @@ final Platform macPlatform = FakePlatform(
);
void main() {
MockProcessManager mockProcessManager;
MockFlutterVersion mockFlutterVersion;
BufferLogger logger;
setUp(() {
mockProcessManager = MockProcessManager();
mockFlutterVersion = MockFlutterVersion();
logger = BufferLogger.test();
});
......@@ -71,87 +68,6 @@ void main() {
});
group('doctor', () {
MockPlistParser mockPlistParser;
MemoryFileSystem fileSystem;
setUp(() {
mockPlistParser = MockPlistParser();
fileSystem = MemoryFileSystem.test();
});
testUsingContext('intellij validator', () async {
const String installPath = '/path/to/intelliJ';
// Uses real filesystem
final ValidationResult result = await IntelliJValidatorTestTarget('Test', installPath, fileSystem: globals.fs).validate();
expect(result.type, ValidationType.partial);
expect(result.statusInfo, 'version test.test.test');
expect(result.messages, hasLength(4));
ValidationMessage message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('IntelliJ '));
expect(message.message, 'IntelliJ at $installPath');
message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('Dart '));
expect(message.message, 'Dart plugin version 162.2485');
message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('Flutter '));
expect(message.message, contains('Flutter plugin version 0.1.3'));
expect(message.message, contains('recommended minimum version'));
}, overrides: noColorTerminalOverride);
testUsingContext('intellij plugins path checking on mac', () async {
when(mockPlistParser.getValueFromFile(any, PlistParser.kCFBundleShortVersionStringKey)).thenReturn('2020.10');
final Directory pluginsDirectory = fileSystem.directory('/foo/bar/Library/Application Support/JetBrains/TestID2020.10/plugins')
..createSync(recursive: true);
final IntelliJValidatorOnMac validator = IntelliJValidatorOnMac('Test', 'TestID', '/path/to/app', fileSystem: fileSystem);
expect(validator.plistFile, '/path/to/app/Contents/Info.plist');
expect(validator.pluginsPath, pluginsDirectory.path);
}, overrides: <Type, Generator>{
Platform: () => macPlatform,
PlistParser: () => mockPlistParser,
FileSystem: () => fileSystem,
ProcessManager: () => mockProcessManager,
FileSystemUtils: () => FileSystemUtils(
fileSystem: fileSystem,
platform: macPlatform,
)
});
testUsingContext('legacy intellij plugins path checking on mac', () async {
when(mockPlistParser.getValueFromFile(any, PlistParser.kCFBundleShortVersionStringKey)).thenReturn('2020.10');
final IntelliJValidatorOnMac validator = IntelliJValidatorOnMac('Test', 'TestID', '/foo', fileSystem: fileSystem);
expect(validator.pluginsPath, '/foo/bar/Library/Application Support/TestID2020.10');
}, overrides: <Type, Generator>{
Platform: () => macPlatform,
PlistParser: () => mockPlistParser,
FileSystem: () => fileSystem,
FileSystemUtils: () => FileSystemUtils(
fileSystem: fileSystem,
platform: macPlatform,
),
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('intellij plugins path checking on mac with override', () async {
when(mockPlistParser.getValueFromFile(any, 'JetBrainsToolboxApp')).thenReturn('/path/to/JetBrainsToolboxApp');
final IntelliJValidatorOnMac validator = IntelliJValidatorOnMac('Test', 'TestID', '/foo', fileSystem: fileSystem);
expect(validator.pluginsPath, '/path/to/JetBrainsToolboxApp.plugins');
}, overrides: <Type, Generator>{
PlistParser: () => mockPlistParser,
Platform: () => macPlatform,
FileSystem: () => fileSystem,
FileSystemUtils: () => FileSystemUtils(
fileSystem: fileSystem,
platform: macPlatform,
),
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('vs code validator when both installed', () async {
final ValidationResult result = await VsCodeValidatorTestTargets.installedWithExtension.validate();
expect(result.type, ValidationType.installed);
......@@ -787,18 +703,6 @@ class NoOpDoctor implements Doctor {
class MockUsage extends Mock implements Usage {}
class IntelliJValidatorTestTarget extends IntelliJValidator {
IntelliJValidatorTestTarget(String title, String installPath, {@required FileSystem fileSystem})
: super(title, installPath, fileSystem: fileSystem);
// Warning: requires real test data.
@override
String get pluginsPath => globals.fs.path.join('test', 'data', 'intellij', 'plugins');
@override
String get version => 'test.test.test';
}
class PassingValidator extends DoctorValidator {
PassingValidator(String name) : super(name);
......
This diff was suppressed by a .gitattributes entry.
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:archive/archive.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/doctor.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';
final Platform macPlatform = FakePlatform(
operatingSystem: 'macos',
environment: <String, String>{'HOME': '/foo/bar'}
);
void main() {
testWithoutContext('Intellij validator can parse plugin manifest from plugin JAR', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
// Create plugin JAR file for Flutter and Dart plugin.
final List<int> flutterPluginBytes = utf8.encode(kIntellijFlutterPluginXml);
final Archive flutterPlugins = Archive();
flutterPlugins.addFile(ArchiveFile('META-INF/plugin.xml', flutterPluginBytes.length, flutterPluginBytes));
fileSystem.file('plugins/flutter-intellij.jar')
..createSync(recursive: true)
..writeAsBytesSync(ZipEncoder().encode(flutterPlugins));
final List<int> dartPluginBytes = utf8.encode(kIntellijDartPluginXml);
final Archive dartPlugins = Archive();
dartPlugins.addFile(ArchiveFile('META-INF/plugin.xml', dartPluginBytes.length, dartPluginBytes));
fileSystem.file('plugins/Dart/lib/Dart.jar')
..createSync(recursive: true)
..writeAsBytesSync(ZipEncoder().encode(dartPlugins));
final ValidationResult result = await IntelliJValidatorTestTarget('', 'path/to/intellij', fileSystem).validate();
expect(result.type, ValidationType.partial);
expect(result.statusInfo, 'version test.test.test');
expect(result.messages, const <ValidationMessage>[
ValidationMessage('IntelliJ at path/to/intellij'),
ValidationMessage.error('Flutter plugin version 0.1.3 - the recommended minimum version is 16.0.0'),
ValidationMessage('Dart plugin version 162.2485'),
ValidationMessage('For information about installing plugins, see\n'
'https://flutter.dev/intellij-setup/#installing-the-plugins')
]);
});
testWithoutContext('Intellij plugins path checking on mac', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory pluginsDirectory = fileSystem.directory('/foo/bar/Library/Application Support/JetBrains/TestID2020.10/plugins')
..createSync(recursive: true);
final IntelliJValidatorOnMac validator = IntelliJValidatorOnMac(
'Test',
'TestID',
'/path/to/app',
fileSystem: fileSystem,
homeDirPath: '/foo/bar',
userMessages: UserMessages(),
plistParser: FakePlistParser(<String, String>{
PlistParser.kCFBundleShortVersionStringKey: '2020.10',
})
);
expect(validator.plistFile, '/path/to/app/Contents/Info.plist');
expect(validator.pluginsPath, pluginsDirectory.path);
});
testWithoutContext('legacy Intellij plugins path checking on mac', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final IntelliJValidatorOnMac validator = IntelliJValidatorOnMac(
'Test',
'TestID',
'/foo',
fileSystem: fileSystem,
homeDirPath: '/foo/bar',
userMessages: UserMessages(),
plistParser: FakePlistParser(<String, String>{
PlistParser.kCFBundleShortVersionStringKey: '2020.10',
})
);
expect(validator.pluginsPath, '/foo/bar/Library/Application Support/TestID2020.10');
});
testWithoutContext('Intellij plugins path checking on mac with JetBrains toolbox override', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final IntelliJValidatorOnMac validator = IntelliJValidatorOnMac(
'Test',
'TestID',
'/foo',
fileSystem: fileSystem,
homeDirPath: '/foo/bar',
userMessages: UserMessages(),
plistParser: FakePlistParser(<String, String>{
'JetBrainsToolboxApp': '/path/to/JetBrainsToolboxApp',
})
);
expect(validator.pluginsPath, '/path/to/JetBrainsToolboxApp.plugins');
});
}
class FakePlistParser extends Fake implements PlistParser {
FakePlistParser(this.values);
final Map<String, String> values;
@override
String getValueFromFile(String plistFilePath, String key) {
return values[key];
}
}
class IntelliJValidatorTestTarget extends IntelliJValidator {
IntelliJValidatorTestTarget(String title, String installPath, FileSystem fileSystem)
: super(title, installPath, fileSystem: fileSystem, userMessages: UserMessages());
@override
String get pluginsPath => 'plugins';
@override
String get version => 'test.test.test';
}
/// These file contents were derived from the META-INF/plugin.xml from an Intellij Flutter
/// plugin installation.
///
/// The file is loacted in a plugin JAR, which can be located by looking at the plugin
/// path for the Intellij and Android Studio validators.
///
/// If more XML contents are needed, prefer modifying these contents over checking
/// in another JAR.
const String kIntellijFlutterPluginXml = r'''
<idea-plugin version="2">
<id>io.flutter</id>
<name>Flutter</name>
<description>Support for developing Flutter applications.</description>
<vendor url="https://github.com/flutter/flutter-intellij">flutter.io</vendor>
<category>Custom Languages</category>
<version>0.1.3</version>
<idea-version since-build="162.1" until-build="163.*"/>
</idea-plugin>
<idea-plugin version="2">
<name>Dart</name>
<version>162.2485</version>
<idea-version since-build="162.1121" until-build="162.*"/>
<description>Support for Dart programming language</description>
<vendor>JetBrains</vendor>
<depends>com.intellij.modules.xml</depends>
<depends optional="true" config-file="dartium-debugger-support.xml">JavaScriptDebugger</depends>
<depends optional="true" config-file="dart-yaml.xml">org.jetbrains.plugins.yaml</depends>
<depends optional="true" config-file="dart-copyright.xml">com.intellij.copyright</depends>
<depends optional="true" config-file="dart-coverage.xml">com.intellij.modules.coverage</depends>
</idea-plugin>
''';
/// These file contents were derived from the META-INF/plugin.xml from an Intellij Dart
/// plugin installation.
///
/// The file is loacted in a plugin JAR, which can be located by looking at the plugin
/// path for the Intellij and Android Studio validators.
///
/// If more XML contents are needed, prefer modifying these contents over checking
/// in another JAR.
const String kIntellijDartPluginXml = r'''
<idea-plugin version="2">
<name>Dart</name>
<version>162.2485</version>
<idea-version since-build="162.1121" until-build="162.*"/>
<description>Support for Dart programming language</description>
<vendor>JetBrains</vendor>
<depends>com.intellij.modules.xml</depends>
<depends optional="true" config-file="dartium-debugger-support.xml">JavaScriptDebugger</depends>
<depends optional="true" config-file="dart-yaml.xml">org.jetbrains.plugins.yaml</depends>
<depends optional="true" config-file="dart-copyright.xml">com.intellij.copyright</depends>
<depends optional="true" config-file="dart-coverage.xml">com.intellij.modules.coverage</depends>
</idea-plugin>
''';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment