blob: 7c819fd44dc1672ef7f058e5a259be2d50eba63f [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library analyzer_cli.src.plugin.plugin_manager;
import 'dart:io';
import 'package:analyzer/src/plugin/plugin_configuration.dart';
import 'package:path/path.dart' as path;
const _manifestFileName = 'plugins.yaml';
/// Given a local configuration (as defined in an analysis options file) and
/// information from a plugin manifest, return plugin info appropriate for
/// configuring this plugin.
PluginInfo combine(PluginInfo localConfig, PluginInfo manifestInfo) {
return new PluginInfo(
name: localConfig.name,
version: manifestInfo.version,
className: manifestInfo.className,
libraryUri: manifestInfo.libraryUri);
}
/// Call-back to allow for the injection of manifest readers that do not need
/// to go to disk (for testing purposes).
typedef String ManifestReader(Uri uri);
/// Wraps a [plugin] info object elaborated with any configuration information
/// extracted from an associated manifest and [status].
class PluginDetails {
/// Plugin status.
final PluginStatus status;
/// Plugin info.
final PluginInfo plugin;
/// Wrap a [plugin] with [status] info.
PluginDetails(this.plugin) : status = PluginStatus.Applicable;
PluginDetails.notApplicable(this.plugin)
: status = PluginStatus.NotApplicable;
PluginDetails.notFound(this.plugin) : status = PluginStatus.NotFound;
}
/// Manages plugin information derived from plugin manifests.
class PluginManager {
/// Mapping from package name to package location.
final Map<String, Uri> _packageMap;
/// The package naming the app to host plugins.
final String hostPackage;
/// Function to perform the reading of manifest URIs. (For testing.)
ManifestReader _manifestReader;
/// Create a plugin manager with backing package map information.
PluginManager(this._packageMap, this.hostPackage,
[ManifestReader manifestReader]) {
_manifestReader =
manifestReader != null ? manifestReader : _findAndReadManifestAtUri;
}
/// Find a plugin manifest describing the given [pluginPackage].
PluginManifest findManifest(String pluginPackage) {
Uri uri = _packageMap[pluginPackage];
String contents = _manifestReader(uri);
if (contents == null) {
return null;
}
return parsePluginManifestString(contents);
}
/// Return [PluginDetails] derived from associated plugin manifests
/// corresponding to plugins specified in the given [config].
Iterable<PluginDetails> getPluginDetails(PluginConfig config) =>
config.plugins.map((PluginInfo localConfig) {
PluginManifest manifest = findManifest(localConfig.name);
return _getDetails(localConfig, manifest);
});
String _findAndReadManifestAtUri(Uri uri) {
File manifestFile = _findManifest(uri);
return manifestFile?.readAsStringSync();
}
File _findManifest(Uri uri) {
if (uri == null) {
return null;
}
Directory directory = new Directory.fromUri(uri);
File file = new File(path.join(directory.path, _manifestFileName));
return file.existsSync() ? file : null;
}
PluginDetails _getDetails(PluginInfo localConfig, PluginManifest manifest) {
if (manifest == null) {
return new PluginDetails.notFound(localConfig);
}
if (!manifest.contributesTo.contains(hostPackage)) {
return new PluginDetails.notApplicable(localConfig);
}
return new PluginDetails(combine(localConfig, manifest.plugin));
}
}
/// Describes plugin status.
enum PluginStatus { Applicable, NotApplicable, NotFound }