Unverified Commit 4e2f82cf authored by Nobuhiro Tabuki's avatar Nobuhiro Tabuki Committed by GitHub

[flutter_tools] change the IntelliJ plugin detection logic. (#68020)

This PR suggests improving the IntelliJ plugin "jar" detection logic.

Previously:
The IntelliJ Flutter plugin was contained flutter-intellij.jar.
Currently:
It is named flutter-intellij-X.Y.Z.jar and does not contain META-INF/plugin.xml.
META-INF/plugin.xml is included in flutter-idea-X.Y.Z.jar.

So this PR changes the rules for searching the plugin's jar file.
Concretely, it looks for the jar file containing META-INF/plugin.xml in the plugin's package directory and reads the package version from its META-INF/plugin.xml.
Co-authored-by: 's avatarJonah Williams <jonahwilliams@google.com>
parent c97ea717
......@@ -15,6 +15,25 @@ import '../doctor.dart';
/// This searches on the provided plugin path for a JAR archive, then
/// unzips it to parse the META-INF/plugin.xml for version information.
///
/// In particular, the Intellij Flutter plugin has a different structure depending on the version.
///
/// For flutter-intellij plugin v49 or lower:
/// flutter-intellij/lib/flutter-intellij.jar ( includes META-INF/plugin.xml )
///
/// For flutter-intellij plugin v50 or higher and for Intellij 2020.2:
/// flutter-intellij/lib/flutter-intellij-X.Y.Z.jar
/// flutter-idea-X.Y.Z.jar ( includes META-INF/plugin.xml )
/// flutter-studio-X.Y.Z.jar
///
/// For flutter-intellij plugin v50 or higher and for Intellij 2020.3:
/// flutter-intellij/lib/flutter-intellij-X.Y.Z.jar
/// flutter-idea-X.Y.Z.jar ( includes META-INF/plugin.xml )
///
/// where X.Y.Z is the version number.
///
/// Intellij Flutter plugin's files can be found here:
/// https://plugins.jetbrains.com/plugin/9212-flutter/versions/stable
///
/// See also:
/// * [IntellijValidator], the validator base class that uses this to check
/// plugin versions.
......@@ -69,17 +88,61 @@ class IntelliJPlugins {
return _fileSystem.isDirectorySync(packagePath);
}
String _readPackageVersion(String packageName) {
final String jarPath = packageName.endsWith('.jar')
? _fileSystem.path.join(pluginsPath, packageName)
: _fileSystem.path.join(pluginsPath, packageName, 'lib', '$packageName.jar');
final File file = _fileSystem.file(jarPath);
if (!file.existsSync()) {
return null;
ArchiveFile _findPluginXml(String packageName) {
final List<File> mainJarFileList = <File>[];
if (packageName.endsWith('.jar')) {
// package exists (checked in _hasPackage)
mainJarFileList.add(_fileSystem.file(_fileSystem.path.join(pluginsPath, packageName)));
} else {
final String packageLibPath =
_fileSystem.path.join(pluginsPath, packageName, 'lib');
if (!_fileSystem.isDirectorySync(packageLibPath)) {
return null;
}
// Collect the files with a file suffix of .jar/.zip that contains the plugin.xml file
final List<File> pluginJarFiles = _fileSystem
.directory(_fileSystem.path.join(pluginsPath, packageName, 'lib'))
.listSync()
.whereType<File>()
.where((File file) {
final String fileExt= _fileSystem.path.extension(file.path);
return fileExt == '.jar' || fileExt == '.zip';
})
.toList();
if (pluginJarFiles.isEmpty) {
return null;
}
// Prefer file with the same suffix as the package name
pluginJarFiles.sort((File a, File b) {
final bool aStartWithPackageName =
a.basename.toLowerCase().startsWith(packageName.toLowerCase());
final bool bStartWithPackageName =
b.basename.toLowerCase().startsWith(packageName.toLowerCase());
if (bStartWithPackageName != aStartWithPackageName) {
return bStartWithPackageName ? 1 : -1;
}
return a.basename.length - b.basename.length;
});
mainJarFileList.addAll(pluginJarFiles);
}
try {
for (final File file in mainJarFileList) {
final Archive archive = ZipDecoder().decodeBytes(file.readAsBytesSync());
final ArchiveFile archiveFile = archive.findFile('META-INF/plugin.xml');
if (archiveFile != null) {
return archiveFile;
}
}
return null;
}
String _readPackageVersion(String packageName) {
try {
final ArchiveFile archiveFile = _findPluginXml(packageName);
if (archiveFile == null) {
return null;
}
final String content = utf8.decode(archiveFile.content as List<int>);
const String versionStartTag = '<version>';
final int start = content.indexOf(versionStartTag);
......
......@@ -69,6 +69,81 @@ void main() {
expect(message.message, contains('recommended minimum version'));
});
testWithoutContext('IntelliJPlugins can read the package version of the flutter-intellij 50.0+/IntelliJ 2020.2+ layout', () async {
final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem);
final Archive flutterIdeaJarArchive = buildSingleFileArchive('META-INF/plugin.xml', r'''
<idea-plugin version="2">
<name>Flutter</name>
<version>50.0</version>
</idea-plugin>
''');
writeFileCreatingDirectories(
fileSystem.path.join(_kPluginsPath, 'flutter-intellij', 'lib', 'flutter-idea-50.0.jar'),
ZipEncoder().encode(flutterIdeaJarArchive),
);
final Archive flutterIntellijJarArchive = buildSingleFileArchive('META-INF/MANIFEST.MF', r'''
Manifest-Version: 1.0
''');
writeFileCreatingDirectories(
fileSystem.path.join(_kPluginsPath, 'flutter-intellij', 'lib', 'flutter-intellij-50.0.jar'),
ZipEncoder().encode(flutterIntellijJarArchive),
);
final List<ValidationMessage> messages = <ValidationMessage>[];
plugins.validatePackage(messages,
<String>[
'flutter-intellij',
'flutter-intellij.jar',
],
'Flutter', 'download-Flutter',
minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
);
final ValidationMessage message = messages.firstWhere(
(ValidationMessage m) => m.message.startsWith('Flutter '));
expect(message.message, contains('Flutter plugin version 50.0'));
});
testWithoutContext('IntelliJPlugins can read the package version of the flutter-intellij 50.0+/IntelliJ 2020.2+ layout(priority is given to packages with the same prefix as packageName)', () async {
final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem);
final Archive flutterIdeaJarArchive = buildSingleFileArchive('META-INF/plugin.xml', r'''
<idea-plugin version="2">
<name>Flutter</name>
<version>50.0</version>
</idea-plugin>
''');
writeFileCreatingDirectories(
fileSystem.path.join(_kPluginsPath, 'flutter-intellij', 'lib', 'flutter-idea-50.0.jar'),
ZipEncoder().encode(flutterIdeaJarArchive),
);
final Archive flutterIntellijJarArchive = buildSingleFileArchive('META-INF/plugin.xml', r'''
<idea-plugin version="2">
<name>Flutter</name>
<version>51.0</version>
</idea-plugin>
''');
writeFileCreatingDirectories(
fileSystem.path.join(_kPluginsPath, 'flutter-intellij', 'lib', 'flutter-intellij-50.0.jar'),
ZipEncoder().encode(flutterIntellijJarArchive),
);
final List<ValidationMessage> messages = <ValidationMessage>[];
plugins.validatePackage(messages,
<String>[
'flutter-intellij',
'flutter-intellij.jar',
],
'Flutter', 'download-Flutter',
minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
);
final ValidationMessage message = messages.firstWhere(
(ValidationMessage m) => m.message.startsWith('Flutter '));
expect(message.message, contains('Flutter plugin version 51.0'));
});
testWithoutContext('IntelliJPlugins not found displays a link to their download site', () async {
final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem);
......@@ -94,11 +169,8 @@ void main() {
final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem);
final Archive dartJarArchive =
buildSingleFileArchive('META-INF/plugin.xml', r'''
<idea-plugin version="2">
<name>Dart</name>
<version>162.2485</version>
</idea-plugin>
buildSingleFileArchive('META-INF/MANIFEST.MF', r'''
Manifest-Version: 1.0
''');
writeFileCreatingDirectories(
fileSystem.path.join(_kPluginsPath, 'Dart', 'lib', 'Other.jar'),
......
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