mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
155 lines
5.6 KiB
Dart
155 lines
5.6 KiB
Dart
// 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 '../base/file_system.dart';
|
|
import '../base/version.dart';
|
|
import '../convert.dart';
|
|
import '../doctor_validator.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.
|
|
///
|
|
/// 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.
|
|
class IntelliJPlugins {
|
|
IntelliJPlugins(this.pluginsPath, {
|
|
required FileSystem fileSystem
|
|
}) : _fileSystem = fileSystem;
|
|
|
|
final FileSystem _fileSystem;
|
|
final String pluginsPath;
|
|
|
|
static final Version kMinFlutterPluginVersion = Version(16, 0, 0);
|
|
static const String kIntellijDartPluginUrl = 'https://plugins.jetbrains.com/plugin/6351-dart';
|
|
static const String kIntellijFlutterPluginUrl = 'https://plugins.jetbrains.com/plugin/9212-flutter';
|
|
|
|
void validatePackage(
|
|
List<ValidationMessage> messages,
|
|
List<String> packageNames,
|
|
String title,
|
|
String url, {
|
|
Version? minVersion,
|
|
}) {
|
|
for (final String packageName in packageNames) {
|
|
if (!_hasPackage(packageName)) {
|
|
continue;
|
|
}
|
|
|
|
final String? versionText = _readPackageVersion(packageName);
|
|
final Version? version = Version.parse(versionText);
|
|
if (version != null && minVersion != null && version < minVersion) {
|
|
messages.add(ValidationMessage.error(
|
|
'$title plugin version $versionText - the recommended minimum version is $minVersion'),
|
|
);
|
|
} else {
|
|
messages.add(ValidationMessage(
|
|
'$title plugin ${version != null ? "version $version" : "installed"}'),
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
messages.add(ValidationMessage(
|
|
'$title plugin can be installed from:',
|
|
contextUrl: url,
|
|
));
|
|
}
|
|
|
|
bool _hasPackage(String packageName) {
|
|
final String packagePath = _fileSystem.path.join(pluginsPath, packageName);
|
|
if (packageName.endsWith('.jar')) {
|
|
return _fileSystem.isFileSync(packagePath);
|
|
}
|
|
return _fileSystem.isDirectorySync(packagePath);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
final int end = content.indexOf('</version>', start);
|
|
return content.substring(start + versionStartTag.length, end);
|
|
} on ArchiveException {
|
|
return null;
|
|
}
|
|
}
|
|
}
|