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'; ...@@ -15,6 +15,25 @@ import '../doctor.dart';
/// This searches on the provided plugin path for a JAR archive, then /// This searches on the provided plugin path for a JAR archive, then
/// unzips it to parse the META-INF/plugin.xml for version information. /// 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: /// See also:
/// * [IntellijValidator], the validator base class that uses this to check /// * [IntellijValidator], the validator base class that uses this to check
/// plugin versions. /// plugin versions.
...@@ -69,17 +88,61 @@ class IntelliJPlugins { ...@@ -69,17 +88,61 @@ class IntelliJPlugins {
return _fileSystem.isDirectorySync(packagePath); return _fileSystem.isDirectorySync(packagePath);
} }
String _readPackageVersion(String packageName) { ArchiveFile _findPluginXml(String packageName) {
final String jarPath = packageName.endsWith('.jar') final List<File> mainJarFileList = <File>[];
? _fileSystem.path.join(pluginsPath, packageName) if (packageName.endsWith('.jar')) {
: _fileSystem.path.join(pluginsPath, packageName, 'lib', '$packageName.jar'); // package exists (checked in _hasPackage)
final File file = _fileSystem.file(jarPath); mainJarFileList.add(_fileSystem.file(_fileSystem.path.join(pluginsPath, packageName)));
if (!file.existsSync()) { } else {
return null; 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 Archive archive = ZipDecoder().decodeBytes(file.readAsBytesSync());
final ArchiveFile archiveFile = archive.findFile('META-INF/plugin.xml'); 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>); final String content = utf8.decode(archiveFile.content as List<int>);
const String versionStartTag = '<version>'; const String versionStartTag = '<version>';
final int start = content.indexOf(versionStartTag); final int start = content.indexOf(versionStartTag);
......
...@@ -69,6 +69,81 @@ void main() { ...@@ -69,6 +69,81 @@ void main() {
expect(message.message, contains('recommended minimum version')); 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 { testWithoutContext('IntelliJPlugins not found displays a link to their download site', () async {
final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem); final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem);
...@@ -94,11 +169,8 @@ void main() { ...@@ -94,11 +169,8 @@ void main() {
final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem); final IntelliJPlugins plugins = IntelliJPlugins(_kPluginsPath, fileSystem: fileSystem);
final Archive dartJarArchive = final Archive dartJarArchive =
buildSingleFileArchive('META-INF/plugin.xml', r''' buildSingleFileArchive('META-INF/MANIFEST.MF', r'''
<idea-plugin version="2"> Manifest-Version: 1.0
<name>Dart</name>
<version>162.2485</version>
</idea-plugin>
'''); ''');
writeFileCreatingDirectories( writeFileCreatingDirectories(
fileSystem.path.join(_kPluginsPath, 'Dart', 'lib', 'Other.jar'), 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