Remove the AnalysisOptionsProcessor

R=scheglov@google.com

Review URL: https://codereview.chromium.org/2559523005 .
This commit is contained in:
Brian Wilkerson 2016-12-07 10:51:33 -08:00
parent 70581541e6
commit 0ea654a068
19 changed files with 59 additions and 1207 deletions

2
DEPS
View file

@ -73,7 +73,7 @@ vars = {
"isolate_tag": "@0.2.3",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "@2.0.2",
"linter_rev": "@17870d56361a95831e1ab32c82a0851ffe34c82b",
"linter_rev": "@592e0f66957df2e548f9f9c788ee384f596fea4e",
"logging_tag": "@0.11.3+1",
"markdown_tag": "@0.11.0",
"matcher_tag": "@0.12.0+2",

View file

@ -10,10 +10,8 @@ import 'dart:convert';
import 'dart:core';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/source/package_map_provider.dart';
@ -30,9 +28,6 @@ import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/lint/config.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/absolute_path.dart';
import 'package:analyzer/src/util/glob.dart';
@ -345,11 +340,6 @@ abstract class ContextManagerCallbacks {
*/
AnalysisContext addContext(Folder folder, AnalysisOptions options);
/**
* The given [file] was removed from the folder analyzed in the [driver].
*/
void applyFileRemoved(AnalysisDriver driver, String file);
/**
* Called when the set of files associated with a context have changed (or
* some of those files have been modified). [changeSet] is the set of
@ -357,6 +347,11 @@ abstract class ContextManagerCallbacks {
*/
void applyChangesToContext(Folder contextFolder, ChangeSet changeSet);
/**
* The given [file] was removed from the folder analyzed in the [driver].
*/
void applyFileRemoved(AnalysisDriver driver, String file);
/**
* Signals that the context manager has started to compute a package map (if
* [computing] is `true`) or has finished (if [computing] is `false`).
@ -635,37 +630,25 @@ class ContextManagerImpl implements ContextManager {
return;
}
// In case options files are removed, revert to defaults.
AnalysisOptionsImpl analysisOptions;
if (optionsRemoved) {
// Start with defaults.
info.context.analysisOptions = new AnalysisOptionsImpl();
// In case options files are removed, revert to defaults.
analysisOptions = new AnalysisOptionsImpl.from(defaultContextOptions);
// Apply inherited options.
options = _toStringMap(_getEmbeddedOptions(info));
if (options != null) {
configureContextOptions(info.context, options);
}
} else {
analysisOptions =
new AnalysisOptionsImpl.from(info.context.analysisOptions);
// Check for embedded options.
Map embeddedOptions = _getEmbeddedOptions(info);
if (embeddedOptions != null) {
options = _toStringMap(new Merger().merge(embeddedOptions, options));
}
}
// Notify options processors.
AnalysisEngine.instance.optionsPlugin.optionsProcessors
.forEach((OptionsProcessor p) {
try {
p.optionsProcessed(info.context, options);
} catch (e, stacktrace) {
AnalysisEngine.instance.logger.logError(
'Error processing analysis options',
new CaughtException(e, stacktrace));
}
});
configureContextOptions(info.context, options);
if (options != null) {
applyToAnalysisOptions(analysisOptions, options);
}
info.context.analysisOptions = analysisOptions;
// Nothing more to do.
if (options == null) {
@ -711,16 +694,6 @@ class ContextManagerImpl implements ContextManager {
}
}
var lintOptions = options['linter'];
if (lintOptions != null) {
LintConfig config = new LintConfig.parseMap(lintOptions);
Iterable<LintRule> lintRules = Registry.ruleRegistry.enabled(config);
if (lintRules.isNotEmpty) {
analysisOptions.lint = true;
analysisOptions.lintRules = lintRules.toList();
}
}
applyToAnalysisOptions(analysisOptions, options);
// Nothing more to do.
@ -1004,8 +977,7 @@ class ContextManagerImpl implements ContextManager {
String contextRoot = info.folder.path;
ContextBuilder builder =
callbacks.createContextBuilder(info.folder, defaultContextOptions);
AnalysisOptions options =
builder.getAnalysisOptions(info.context, contextRoot);
AnalysisOptions options = builder.getAnalysisOptions(contextRoot);
SourceFactory factory = builder.createSourceFactory(contextRoot, options);
info.context.analysisOptions = options;
info.context.sourceFactory = factory;

View file

@ -7,18 +7,10 @@
library analyzer.plugin.options;
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/plugin/options_plugin.dart';
import 'package:plugin/plugin.dart';
import 'package:yaml/yaml.dart';
/// The identifier of the extension point that allows plugins to access
/// options defined in the analysis options file. The object used as an
/// extension must be an [OptionsProcessor].
final String OPTIONS_PROCESSOR_EXTENSION_POINT_ID = Plugin.join(
OptionsPlugin.UNIQUE_IDENTIFIER,
OptionsPlugin.OPTIONS_PROCESSOR_EXTENSION_POINT);
/// The identifier of the extension point that allows plugins to validate
/// options defined in the analysis options file. The object used as an
/// extension must be an [OptionsValidator].
@ -26,9 +18,7 @@ final String OPTIONS_VALIDATOR_EXTENSION_POINT_ID = Plugin.join(
OptionsPlugin.UNIQUE_IDENTIFIER,
OptionsPlugin.OPTIONS_VALIDATOR_EXTENSION_POINT);
/// Processes options defined in the analysis options file.
///
/// Clients may implement this class when implementing plugins.
/// Validates options as defined in an analysis options file.
///
/// The options file format is intentionally very open-ended, giving clients
/// utmost flexibility in defining their own options. The only hardfast
@ -55,29 +45,9 @@ final String OPTIONS_VALIDATOR_EXTENSION_POINT_ID = Plugin.join(
///
/// bool useMultiPackage =
/// options['compiler']['resolver']['useMultiPackage'];
abstract class OptionsProcessor {
/// Called when an error occurs in processing options.
void onError(Exception exception);
/// Called when an options file is processed.
///
/// The options file is processed on analyzer initialization and
/// subsequently when the file is changed on disk. In the event of a
/// change notification, note that the notification simply indicates
/// a change on disk. Content in specific option scopes may or may not
/// be different. It is up to the implementer to check whether specific
/// options have changed and to handle those changes appropriately. In
/// addition to the [options] map, the associated analysis [context] is
/// provided as well to allow for context-specific configuration.
void optionsProcessed(AnalysisContext context, Map<String, Object> options);
}
/// Validates options as defined in an analysis options file.
///
/// Clients may implement this class when implementing plugins.
///
/// See [OptionsProcessor] for a description of the options file format.
///
abstract class OptionsValidator {
/// Validate [options], reporting any errors to the given [reporter].
void validate(ErrorReporter reporter, Map<String, YamlNode> options);

View file

@ -9,7 +9,6 @@ import 'dart:core';
import 'package:analyzer/context/declared_variables.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/source/package_map_resolver.dart';
@ -102,7 +101,7 @@ class ContextBuilder {
AnalysisContext buildContext(String path) {
InternalAnalysisContext context =
AnalysisEngine.instance.createAnalysisContext();
AnalysisOptions options = getAnalysisOptions(context, path);
AnalysisOptions options = getAnalysisOptions(path);
context.contentCache = contentCache;
context.sourceFactory = createSourceFactory(path, options);
context.analysisOptions = options;
@ -325,15 +324,13 @@ class ContextBuilder {
}
/**
* Return the analysis options that should be used when the given [context] is
* used to analyze code in the directory with the given [path].
* Return the analysis options that should be used to analyze code in the
* directory with the given [path].
*/
AnalysisOptions getAnalysisOptions(AnalysisContext context, String path) {
AnalysisOptions getAnalysisOptions(String path) {
AnalysisOptionsImpl options = createDefaultOptions();
File optionsFile = getOptionsFile(path);
if (optionsFile != null) {
List<OptionsProcessor> optionsProcessors =
AnalysisEngine.instance.optionsPlugin.optionsProcessors;
// TODO(danrubel) restructure so that we don't recalculate the package map
// more than once per path.
Packages packages = createPackageMap(path);
@ -348,11 +345,9 @@ class ContextBuilder {
Map<String, YamlNode> optionMap =
new AnalysisOptionsProvider(sourceFactory)
.getOptionsFromFile(optionsFile);
optionsProcessors.forEach(
(OptionsProcessor p) => p.optionsProcessed(context, optionMap));
applyToAnalysisOptions(options, optionMap);
} on Exception catch (exception) {
optionsProcessors.forEach((OptionsProcessor p) => p.onError(exception));
} catch (_) {
// Ignore exceptions thrown while trying to load the options file.
}
}
return options;

View file

@ -13,10 +13,6 @@ import 'package:plugin/plugin.dart';
/// by applications that want to consume options defined in the analysis
/// options file.
class OptionsPlugin implements Plugin {
/// The simple identifier of the extension point that allows plugins to
/// register new options processors.
static const String OPTIONS_PROCESSOR_EXTENSION_POINT = 'optionsProcessor';
/// The simple identifier of the extension point that allows plugins to
/// register new options validators.
static const String OPTIONS_VALIDATOR_EXTENSION_POINT = 'optionsValidator';
@ -24,18 +20,10 @@ class OptionsPlugin implements Plugin {
/// The unique identifier of this plugin.
static const String UNIQUE_IDENTIFIER = 'options.core';
/// The extension point that allows plugins to register new options
/// processors.
ExtensionPoint<OptionsProcessor> optionsProcessorExtensionPoint;
/// The extension point that allows plugins to register new options
/// validators.
ExtensionPoint<OptionsValidator> optionsValidatorExtensionPoint;
/// All contributed options processors.
List<OptionsProcessor> get optionsProcessors =>
optionsProcessorExtensionPoint?.extensions ?? const <OptionsProcessor>[];
/// All contributed options validators.
List<OptionsValidator> get optionsValidators =>
optionsValidatorExtensionPoint?.extensions ?? const <OptionsValidator>[];
@ -45,9 +33,6 @@ class OptionsPlugin implements Plugin {
@override
void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
optionsProcessorExtensionPoint = new ExtensionPoint<OptionsProcessor>(
this, OPTIONS_PROCESSOR_EXTENSION_POINT, null);
registerExtensionPoint(optionsProcessorExtensionPoint);
optionsValidatorExtensionPoint = new ExtensionPoint<OptionsValidator>(
this, OPTIONS_VALIDATOR_EXTENSION_POINT, null);
registerExtensionPoint(optionsValidatorExtensionPoint);

View file

@ -1,198 +0,0 @@
// 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.src.plugin.plugin_configuration;
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:yaml/yaml.dart';
const _analyzerOptionScope = 'analyzer';
const _pluginOptionScope = 'plugins';
/// Parse the given string into a plugin manifest.
PluginManifest parsePluginManifestString(String manifestSource) {
var yaml = loadYaml(manifestSource);
if (yaml == null) {
return null;
}
_verifyMap(yaml, 'plugin manifest');
Iterable<String> pluginHost = _parseHosts(yaml['contributes_to']);
PluginInfo plugin = _parsePlugin(yaml);
return new PluginManifest(contributesTo: pluginHost, plugin: plugin);
}
String _asString(dynamic yaml) {
if (yaml != null && yaml is! String) {
throw new PluginConfigFormatException(
'Unable to parse pugin manifest, '
'expected `String`, got `${yaml.runtimeType}`',
yaml);
}
return yaml;
}
Iterable<String> _parseHosts(dynamic yaml) {
List<String> hosts = <String>[];
if (yaml is String) {
hosts.add(yaml);
} else if (yaml is YamlList) {
yaml.forEach((h) => hosts.add(_asString(h)));
}
return hosts;
}
PluginInfo _parsePlugin(dynamic yaml) {
if (yaml != null) {
_verifyMap(yaml, 'plugin manifest');
return new PluginInfo._fromYaml(details: yaml);
}
return null;
}
PluginInfo _processPluginMapping(dynamic name, dynamic details) {
if (name is String) {
if (details is String) {
return new PluginInfo(name: name, version: details);
}
if (details is YamlMap) {
return new PluginInfo._fromYaml(name: name, details: details);
}
}
return null;
}
_verifyMap(dynamic yaml, String context) {
if (yaml is! YamlMap) {
throw new PluginConfigFormatException(
'Unable to parse $context, '
'expected `YamlMap`, got `${yaml.runtimeType}`',
yaml);
}
}
/// A callback for error handling.
typedef ErrorHandler(Exception e);
/// Describes plugin configuration information as extracted from an
/// analysis options map or plugin manifest.
class PluginConfig {
final Iterable<PluginInfo> plugins;
PluginConfig(this.plugins);
/// Create a plugin configuration from an options map.
factory PluginConfig.fromOptions(Map<String, Object> options) {
List<PluginInfo> plugins = [];
var analyzerOptions = options[_analyzerOptionScope];
if (analyzerOptions != null) {
//TODO(pq): handle "raw" maps (https://github.com/dart-lang/sdk/issues/25126)
if (analyzerOptions is YamlMap) {
var pluginConfig = analyzerOptions[_pluginOptionScope];
if (pluginConfig is YamlMap) {
pluginConfig.forEach((name, details) {
var plugin = _processPluginMapping(name, details);
if (plugin != null) {
plugins.add(plugin);
}
});
} else {
// Anything but an empty list of plugins is treated as a format error.
if (pluginConfig != null) {
throw new PluginConfigFormatException(
'Unrecognized plugin config format, expected `YamlMap`, '
'got `${pluginConfig.runtimeType}`',
pluginConfig);
}
}
}
}
return new PluginConfig(plugins);
}
}
/// Thrown on bad plugin config format.
class PluginConfigFormatException implements Exception {
/// Descriptive message.
final message;
/// The `plugin:` yaml node for generating detailed error feedback.
final yamlNode;
PluginConfigFormatException(this.message, this.yamlNode);
}
/// Extracts plugin config details from analysis options.
class PluginConfigOptionsProcessor extends OptionsProcessor {
final ErrorHandler _errorHandler;
PluginConfig _config;
PluginConfigOptionsProcessor([this._errorHandler]);
/// The processed plugin config.
PluginConfig get config => _config;
@override
void onError(Exception exception) {
if (_errorHandler != null) {
_errorHandler(exception);
}
}
@override
void optionsProcessed(AnalysisContext context, Map<String, Object> options) {
_config = new PluginConfig.fromOptions(options);
}
}
/// Describes plugin information.
class PluginInfo {
final String name;
final String className;
final String version;
final String libraryUri;
final String packageName;
final String path;
PluginInfo(
{this.name,
this.version,
this.className,
this.libraryUri,
this.packageName,
this.path});
factory PluginInfo._fromYaml({String name, YamlMap details}) =>
new PluginInfo(
name: name,
version: _asString(details['version']),
className: _asString(details['class_name']),
libraryUri: _asString(details['library_uri']),
packageName: _asString(details['package_name']),
path: _asString(details['path']));
}
/// Plugin manifests accompany plugin packages, providing
/// configuration information for published plugins.
///
/// Provisionally, plugin manifests live in a file `plugin.yaml`
/// at the root of the plugin package.
///
/// my_plugin/
/// bin/
/// lib/
/// plugin.yaml
/// pubspec.yaml
///
/// Provisional manifest file format:
///
/// class_name: MyAnalyzerPlugin
/// library_uri: 'my_plugin/my_analyzer_plugin.dart'
/// contributes_to: analyzer
class PluginManifest {
PluginInfo plugin;
Iterable<String> contributesTo;
PluginManifest({this.plugin, this.contributesTo});
}

View file

@ -14,6 +14,9 @@ import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/lint/config.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/task/general.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer/task/general.dart';
@ -35,12 +38,6 @@ void applyToAnalysisOptions(
_processor.applyToAnalysisOptions(options, optionMap);
}
/// Configure this [context] based on configuration details specified in
/// the given [options]. If [options] is `null`, default values are applied.
void configureContextOptions(
AnalysisContext context, Map<String, Object> options) =>
_processor.configure(context, options);
/// `analyzer` analysis options constants.
class AnalyzerOptions {
static const String analyzer = 'analyzer';
@ -513,109 +510,13 @@ class _OptionsProcessor {
var excludes = analyzer[AnalyzerOptions.exclude];
_applyExcludes(options, excludes);
}
}
/// Configure [context] based on the given [options] (which can be `null`
/// to restore [defaults]).
void configure(AnalysisContext context, Map<String, Object> options) {
if (options == null) {
options = defaults;
}
var analyzer = options[AnalyzerOptions.analyzer];
if (analyzer is Map) {
// Set strong mode (default is false).
var strongMode = analyzer[AnalyzerOptions.strong_mode];
setStrongMode(context, strongMode);
// Set filters.
var filters = analyzer[AnalyzerOptions.errors];
setProcessors(context, filters);
// Process language options.
var language = analyzer[AnalyzerOptions.language];
setLanguageOptions(context, language);
// Process excludes.
var excludes = analyzer[AnalyzerOptions.exclude];
setExcludes(context, excludes);
}
}
void setExcludes(AnalysisContext context, Object excludes) {
if (excludes is YamlList) {
List<String> excludeList = toStringList(excludes);
if (excludeList != null) {
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
options.excludePatterns = excludeList;
context.analysisOptions = options;
}
}
}
void setLanguageOption(
AnalysisContext context, Object feature, Object value) {
if (feature == AnalyzerOptions.enableAssertInitializer) {
if (isTrue(value)) {
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
options.enableAssertInitializer = true;
context.analysisOptions = options;
}
}
if (feature == AnalyzerOptions.enableStrictCallChecks) {
if (isTrue(value)) {
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
options.enableStrictCallChecks = true;
context.analysisOptions = options;
}
}
if (feature == AnalyzerOptions.enableSuperMixins) {
if (isTrue(value)) {
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
options.enableSuperMixins = true;
context.analysisOptions = options;
}
}
}
void setLanguageOptions(AnalysisContext context, Object configs) {
if (configs is YamlMap) {
configs.nodes.forEach((k, v) {
if (k is YamlScalar && v is YamlScalar) {
String feature = k.value?.toString();
setLanguageOption(context, feature, v.value);
}
});
} else if (configs is Map) {
configs.forEach((k, v) => setLanguageOption(context, k, v));
}
}
void setProcessors(AnalysisContext context, Object codes) {
ErrorConfig config = new ErrorConfig(codes);
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
options.errorProcessors = config.processors;
context.analysisOptions = options;
}
void setStrongMode(AnalysisContext context, Object strongMode) {
if (strongMode is Map) {
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
_applyStrongOptions(options, strongMode);
context.analysisOptions = options;
} else {
strongMode = strongMode is bool ? strongMode : false;
if (context.analysisOptions.strongMode != strongMode) {
AnalysisOptionsImpl options =
new AnalysisOptionsImpl.from(context.analysisOptions);
options.strongMode = strongMode;
context.analysisOptions = options;
LintConfig config = parseConfig(optionMap);
if (config != null) {
Iterable<LintRule> lintRules = Registry.ruleRegistry.enabled(config);
if (lintRules.isNotEmpty) {
options.lint = true;
options.lintRules = lintRules.toList();
}
}
}
@ -635,6 +536,8 @@ class _OptionsProcessor {
if (boolValue != null) {
if (feature == AnalyzerOptions.enableAssertInitializer) {
options.enableAssertInitializer = boolValue;
} else if (feature == AnalyzerOptions.enableStrictCallChecks) {
options.enableStrictCallChecks = true;
} else if (feature == AnalyzerOptions.enableSuperMixins) {
options.enableSuperMixins = boolValue;
}

View file

@ -153,7 +153,7 @@ ErrorProcessor processor;
void configureOptions(String options) {
Map<String, YamlNode> optionMap =
optionsProvider.getOptionsFromString(options);
configureContextOptions(context, optionMap);
applyToAnalysisOptions(context.analysisOptions, optionMap);
}
ErrorProcessor getProcessor(AnalysisError error) =>

View file

@ -6,18 +6,15 @@ library analyzer.test.src.context.context_builder_test;
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/generated/bazel.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/plugin/options_plugin.dart';
import 'package:package_config/packages.dart';
import 'package:package_config/src/packages_impl.dart';
import 'package:path/path.dart' as path;
import 'package:plugin/src/plugin_impl.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@ -513,8 +510,7 @@ linter:
- empty_constructor_bodies
''');
AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
AnalysisOptions options = builder.getAnalysisOptions(context, path);
AnalysisOptions options = builder.getAnalysisOptions(path);
_expectEqualOptions(options, expected);
}
@ -536,24 +532,8 @@ analyzer:
enableSuperMixins : true
''');
AnalysisEngine engine = AnalysisEngine.instance;
OptionsPlugin plugin = engine.optionsPlugin;
plugin.registerExtensionPoints((_) {});
try {
_TestOptionsProcessor processor = new _TestOptionsProcessor();
processor.expectedOptions = <String, Object>{
'analyzer': {
'language': {'enableSuperMixins': true}
}
};
(plugin.optionsProcessorExtensionPoint as ExtensionPointImpl)
.add(processor);
AnalysisContext context = engine.createAnalysisContext();
AnalysisOptions options = builder.getAnalysisOptions(context, path);
_expectEqualOptions(options, expected);
} finally {
plugin.registerExtensionPoints((_) {});
}
AnalysisOptions options = builder.getAnalysisOptions(path);
_expectEqualOptions(options, expected);
}
void test_getAnalysisOptions_includes() {
@ -589,26 +569,8 @@ analyzer:
enableSuperMixins : true
''');
AnalysisEngine engine = AnalysisEngine.instance;
OptionsPlugin plugin = engine.optionsPlugin;
plugin.registerExtensionPoints((_) {});
try {
_TestOptionsProcessor processor = new _TestOptionsProcessor();
processor.expectedOptions = <String, Object>{
'analyzer': {
'language': {'enableSuperMixins': true}
},
'foo': {'bar': 'baz'},
'two': {'boo': 'newt'},
};
(plugin.optionsProcessorExtensionPoint as ExtensionPointImpl)
.add(processor);
AnalysisContext context = engine.createAnalysisContext();
AnalysisOptions options = builder.getAnalysisOptions(context, path);
_expectEqualOptions(options, expected);
} finally {
plugin.registerExtensionPoints((_) {});
}
AnalysisOptions options = builder.getAnalysisOptions(path);
_expectEqualOptions(options, expected);
}
void test_getAnalysisOptions_invalid() {
@ -617,20 +579,8 @@ analyzer:
pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
resourceProvider.newFile(filePath, ';');
AnalysisEngine engine = AnalysisEngine.instance;
OptionsPlugin plugin = engine.optionsPlugin;
plugin.registerExtensionPoints((_) {});
try {
_TestOptionsProcessor processor = new _TestOptionsProcessor();
(plugin.optionsProcessorExtensionPoint as ExtensionPointImpl)
.add(processor);
AnalysisContext context = engine.createAnalysisContext();
AnalysisOptions options = builder.getAnalysisOptions(context, path);
expect(options, isNotNull);
expect(processor.errorCount, 1);
} finally {
plugin.registerExtensionPoints((_) {});
}
AnalysisOptions options = builder.getAnalysisOptions(path);
expect(options, isNotNull);
}
void test_getAnalysisOptions_noDefault_noOverrides() {
@ -645,8 +595,7 @@ linter:
- empty_constructor_bodies
''');
AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
AnalysisOptions options = builder.getAnalysisOptions(context, path);
AnalysisOptions options = builder.getAnalysisOptions(path);
_expectEqualOptions(options, new AnalysisOptionsImpl());
}
@ -664,8 +613,7 @@ analyzer:
enableSuperMixins : true
''');
AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
AnalysisOptions options = builder.getAnalysisOptions(context, path);
AnalysisOptions options = builder.getAnalysisOptions(path);
_expectEqualOptions(options, expected);
}
@ -783,27 +731,3 @@ class EmbedderYamlLocatorTest extends EmbedderRelatedTest {
expect(locator.embedderYamls, hasLength(1));
}
}
class _TestOptionsProcessor implements OptionsProcessor {
Map<String, Object> expectedOptions = null;
int errorCount = 0;
@override
void onError(Exception exception) {
errorCount++;
}
@override
void optionsProcessed(AnalysisContext context, Map<String, Object> options) {
if (expectedOptions == null) {
fail('Unexpected invocation of optionsProcessed');
}
expect(options, hasLength(expectedOptions.length));
for (String key in expectedOptions.keys) {
expect(options.containsKey(key), isTrue, reason: 'missing key $key');
expect(options[key], expectedOptions[key],
reason: 'values for key $key do not match');
}
}
}

View file

@ -1,127 +0,0 @@
// 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.test.src.plugin.plugin_config_test;
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/src/plugin/plugin_configuration.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
main() {
group('plugin config tests', () {
group('parsing', () {
test('plugin map', () {
const optionsSrc = '''
analyzer:
plugins:
my_plugin1: ^0.1.0 #shorthand
my_plugin2:
version: ^0.2.0
my_plugin3:
class_name: MyPlugin
library_uri: myplugin/myplugin.dart
path: '/u/disk/src/'
''';
var config = parseConfig(optionsSrc);
var plugins = pluginsSortedByName(config.plugins);
expect(plugins, hasLength(3));
expect(plugins[0].name, equals('my_plugin1'));
expect(plugins[0].version, equals('^0.1.0'));
expect(plugins[1].name, equals('my_plugin2'));
expect(plugins[1].version, equals('^0.2.0'));
expect(plugins[2].name, equals('my_plugin3'));
expect(plugins[2].version, isNull);
expect(plugins[2].path, equals('/u/disk/src/'));
expect(plugins[2].libraryUri, equals('myplugin/myplugin.dart'));
expect(plugins[2].className, equals('MyPlugin'));
});
test('plugin map (empty)', () {
const optionsSrc = '''
analyzer:
plugins:
# my_plugin1: ^0.1.0 #shorthand
''';
var config = parseConfig(optionsSrc);
// Commented out plugins shouldn't cause a parse failure.
expect(config.plugins, hasLength(0));
});
test('plugin manifest', () {
const manifestSrc = '''
class_name: AnalyzerPlugin
library_uri: myplugin/analyzer_plugin.dart
contributes_to: analyzer
''';
var manifest = parsePluginManifestString(manifestSrc);
var plugin = manifest.plugin;
expect(plugin.libraryUri, equals('myplugin/analyzer_plugin.dart'));
expect(plugin.className, equals('AnalyzerPlugin'));
expect(manifest.contributesTo, unorderedEquals(['analyzer']));
});
test('plugin manifest (contributes_to list)', () {
const manifestSrc = '''
class_name: AnalyzerPlugin
library_uri: myplugin/analyzer_plugin.dart
contributes_to:
- analyzer
- analysis_server
''';
var manifest = parsePluginManifestString(manifestSrc);
var plugin = manifest.plugin;
expect(plugin.libraryUri, equals('myplugin/analyzer_plugin.dart'));
expect(plugin.className, equals('AnalyzerPlugin'));
expect(manifest.contributesTo,
unorderedEquals(['analyzer', 'analysis_server']));
});
group('errors', () {
test('bad config format', () {
const optionsSrc = '''
analyzer:
plugins:
- my_plugin1
- my_plugin2
''';
try {
parseConfig(optionsSrc);
fail('expected PluginConfigFormatException');
} on PluginConfigFormatException catch (e) {
expect(
e.message,
equals(
'Unrecognized plugin config format, expected `YamlMap`, got `YamlList`'));
expect(e.yamlNode, new isInstanceOf<YamlList>());
}
});
test('bad manifest format', () {
const manifestSource = '''
library_uri:
- should be a scalar uri
''';
try {
parsePluginManifestString(manifestSource);
fail('expected PluginConfigFormatException');
} on PluginConfigFormatException catch (e) {
expect(
e.message,
equals(
'Unable to parse pugin manifest, expected `String`, got `YamlList`'));
expect(e.yamlNode, new isInstanceOf<YamlList>());
}
});
});
});
});
}
PluginConfig parseConfig(String optionsSrc) {
var options = new AnalysisOptionsProvider().getOptionsFromString(optionsSrc);
return new PluginConfig.fromOptions(options);
}
List<PluginInfo> pluginsSortedByName(Iterable<PluginInfo> plugins) =>
plugins.toList()..sort((p1, p2) => p1.name.compareTo(p2.name));

View file

@ -38,7 +38,7 @@ class ContextConfigurationTest extends AbstractContextTest {
AnalysisOptions get analysisOptions => context.analysisOptions;
configureContext(String optionsSource) =>
configureContextOptions(context, parseOptions(optionsSource));
applyToAnalysisOptions(analysisOptions, parseOptions(optionsSource));
Map<String, YamlNode> parseOptions(String source) =>
optionsProvider.getOptionsFromString(source);
@ -87,7 +87,7 @@ analyzer:
unused_local_variable: error
''');
List<ErrorProcessor> processors = context.analysisOptions.errorProcessors;
List<ErrorProcessor> processors = analysisOptions.errorProcessors;
expect(processors, hasLength(2));
var unused_local = new AnalysisError(
@ -118,7 +118,7 @@ analyzer:
- 'test/**'
''');
List<String> excludes = context.analysisOptions.excludePatterns;
List<String> excludes = analysisOptions.excludePatterns;
expect(excludes, unorderedEquals(['foo/bar.dart', 'test/**']));
}

View file

@ -9,7 +9,6 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'command_line/test_all.dart' as command_line;
import 'context/test_all.dart' as context;
import 'dart/test_all.dart' as dart;
import 'plugin/plugin_config_test.dart' as plugin;
import 'source/test_all.dart' as source;
import 'summary/test_all.dart' as summary;
import 'task/test_all.dart' as task;
@ -21,7 +20,6 @@ main() {
command_line.main();
context.main();
dart.main();
plugin.main();
source.main();
summary.main();
task.main();

View file

@ -1,211 +0,0 @@
// 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.boot_loader;
import 'dart:async';
import 'dart:isolate';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/generated/engine.dart' as engine;
import 'package:analyzer/src/plugin/plugin_configuration.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/src/yaml_node.dart';
const _analyzerPackageName = 'analyzer';
/// Return non-null if there is a validation issue with this plugin.
String validate(PluginInfo plugin) {
var missing = <String>[];
if (plugin.className == null) {
missing.add('class name');
}
if (plugin.libraryUri == null) {
missing.add('library uri');
}
if (missing.isEmpty) {
// All good.
return null;
}
return 'Plugin ${plugin.name} skipped, config missing: ${missing.join(", ")}';
}
List<PluginInfo> _validate(Iterable<PluginInfo> plugins) {
List<PluginInfo> validated = <PluginInfo>[];
plugins.forEach((PluginInfo plugin) {
String validation = validate(plugin);
if (validation != null) {
errorSink.writeln(validation);
} else {
validated.add(plugin);
}
});
return validated;
}
/// Source code assembler.
class Assembler {
/// Plugins to configure.
final Iterable<PluginInfo> plugins;
/// Create an assembler for the given plugin [config].
Assembler(this.plugins);
/// A string enumerating required package `import`s.
String get enumerateImports =>
plugins.map((PluginInfo p) => "import '${p.libraryUri}';").join('\n');
/// A string listing initialized plugin instances.
String get pluginList =>
plugins.map((PluginInfo p) => 'new ${p.className}()').join(', ');
/// Create a file containing a `main()` suitable for loading in spawned
/// isolate.
String createMain() => _generateMain();
String _generateMain() => """
// 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.
// This code was auto-generated, is not intended to be edited, and is subject to
// significant change. Please see the README file for more information.
import 'package:analyzer_cli/src/driver.dart';
$enumerateImports
void main(List<String> args) {
var starter = new Driver();
starter.userDefinedPlugins = [$pluginList];
starter.start(args);
}
""";
}
/// Given environment information extracted from command-line `args`, creates a
/// a loadable analyzer "image".
class BootLoader {
/// Emits an error message to [errorSink] if plugin config can't be read.
static final ErrorHandler _pluginConfigErrorHandler = (Exception e) {
String details;
if (e is PluginConfigFormatException) {
details = e.message;
var node = e.yamlNode;
if (node is YamlNode) {
SourceLocation location = node.span.start;
details += ' (line ${location.line}, column ${location.column})';
}
} else {
details = e.toString();
}
errorSink.writeln('Plugin configuration skipped: $details');
};
/// Reads plugin config info from the analysis options file.
PluginConfigOptionsProcessor _pluginOptionsProcessor =
new PluginConfigOptionsProcessor(_pluginConfigErrorHandler);
/// Create a loadable analyzer image configured with plugins derived from
/// the given analyzer command-line `args`.
Image createImage(List<String> args) {
// Parse commandline options.
CommandLineOptions options = CommandLineOptions.parse(args);
// Process analysis options file (and notify all interested parties).
_processAnalysisOptions(options);
// TODO(pquitslund): Pass in .packages info
return new Image(_pluginOptionsProcessor.config,
args: args, packageRootPath: options.packageRootPath);
}
File _getOptionsFile(
CommandLineOptions options, ResourceProvider resourceProvider) {
String analysisOptionsFile = options.analysisOptionsFile;
if (analysisOptionsFile != null) {
return resourceProvider.getFile(analysisOptionsFile);
}
File file =
resourceProvider.getFile(engine.AnalysisEngine.ANALYSIS_OPTIONS_FILE);
if (!file.exists) {
file = resourceProvider
.getFile(engine.AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
}
return file;
}
void _processAnalysisOptions(CommandLineOptions commandLineOptions) {
// Determine options file path.
try {
File file = _getOptionsFile(
commandLineOptions, PhysicalResourceProvider.INSTANCE);
AnalysisOptionsProvider analysisOptionsProvider =
new AnalysisOptionsProvider();
Map<String, YamlNode> options =
analysisOptionsProvider.getOptionsFromFile(file);
//TODO(pq): thread in proper context.
var temporaryContext = new AnalysisContextImpl();
_pluginOptionsProcessor.optionsProcessed(temporaryContext, options);
} on Exception catch (e) {
_pluginOptionsProcessor.onError(e);
}
}
}
/// A loadable "image" of a a configured analyzer instance.
class Image {
/// (Optional) package root path.
final String packageRootPath;
/// (Optional) package map.
final Map<String, Uri> packages;
/// (Optional) args to be passed on to the loaded main.
final List<String> args;
/// Plugin configuration.
final PluginConfig config;
/// Create an image with the given [config] and optionally [packages],
/// [packageRootPath], and command line [args].
Image(this.config, {this.packages, this.packageRootPath, this.args});
/// Load this image.
///
/// Loading an image consists in assembling an analyzer `main()`, configured
/// to include the appropriate analyzer plugins as specified in
/// `.analyzer_options` which is then run in a spawned isolate.
Future load() {
List<PluginInfo> plugins = _validate(config.plugins);
String mainSource = new Assembler(plugins).createMain();
Completer completer = new Completer();
ReceivePort exitListener = new ReceivePort();
exitListener.listen((data) {
completer.complete();
exitListener.close();
});
Uri uri =
Uri.parse('data:application/dart;charset=utf-8,${Uri.encodeComponent(
mainSource)}');
// TODO(pquitslund): update once .packages are supported.
String packageRoot =
packageRootPath != null ? packageRootPath : './packages';
Uri packageUri = new Uri.file(packageRoot);
Isolate.spawnUri(uri, args, null /* msg */,
packageRoot: packageUri, onExit: exitListener.sendPort);
return completer.future;
}
}

View file

@ -12,7 +12,6 @@ import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart' as file_system;
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/source/package_map_provider.dart';
@ -770,29 +769,21 @@ class Driver implements CommandLineStarter {
AnalysisContext context,
CommandLineOptions options) {
file_system.File file = _getOptionsFile(resourceProvider, options);
List<OptionsProcessor> optionsProcessors =
AnalysisEngine.instance.optionsPlugin.optionsProcessors;
try {
AnalysisOptionsProvider analysisOptionsProvider =
new AnalysisOptionsProvider(sourceFactory);
Map<String, YamlNode> optionMap =
analysisOptionsProvider.getOptionsFromFile(file);
optionsProcessors.forEach(
(OptionsProcessor p) => p.optionsProcessed(context, optionMap));
AnalysisOptionsProvider analysisOptionsProvider =
new AnalysisOptionsProvider(sourceFactory);
Map<String, YamlNode> optionMap =
analysisOptionsProvider.getOptionsFromFile(file);
// Fill in lint rule defaults in case lints are enabled and rules are
// not specified in an options file.
if (options.lints && !containsLintRuleEntry(optionMap)) {
setLints(context, linterPlugin.contributedRules);
}
// Fill in lint rule defaults in case lints are enabled and rules are
// not specified in an options file.
if (options.lints && !containsLintRuleEntry(optionMap)) {
setLints(context, linterPlugin.contributedRules);
}
// Ask engine to further process options.
if (optionMap != null) {
configureContextOptions(context, optionMap);
}
} on Exception catch (e) {
optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
// Ask engine to further process options.
if (optionMap != null) {
applyToAnalysisOptions(context.analysisOptions, optionMap);
}
}
}

View file

@ -1,110 +0,0 @@
// 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 }

View file

@ -2,7 +2,6 @@
// 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.
import 'boot_loader_test.dart' as boot_loader;
import 'build_mode_test.dart' as build_mode_test;
import 'driver_test.dart' as driver;
import 'embedder_test.dart' as embedder;
@ -10,14 +9,12 @@ import 'error_test.dart' as error;
import 'options_test.dart' as options;
import 'package_prefix_test.dart' as package_prefix;
import 'perf_report_test.dart' as perf;
import 'plugin_manager_test.dart' as plugin_manager;
import 'reporter_test.dart' as reporter;
import 'sdk_ext_test.dart' as sdk_ext;
import 'super_mixin_test.dart' as super_mixin;
//import 'strong_mode_test.dart' as strong_mode;
main() {
boot_loader.main();
build_mode_test.main();
driver.main();
embedder.main();
@ -28,7 +25,6 @@ main() {
error.main();
options.main();
perf.main();
plugin_manager.main();
reporter.main();
super_mixin.main();
package_prefix.main();

View file

@ -1,96 +0,0 @@
// Copyright (c) 2016, 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.test.boot_loader_test;
import 'dart:io';
import 'package:analyzer/src/plugin/plugin_configuration.dart';
import 'package:analyzer_cli/src/boot_loader.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'utils.dart';
main() {
StringSink savedOutSink, savedErrorSink;
int savedExitCode;
ExitHandler savedExitHandler;
/// Base setup.
_setUp() {
savedOutSink = outSink;
savedErrorSink = errorSink;
savedExitHandler = exitHandler;
savedExitCode = exitCode;
exitHandler = (code) => exitCode = code;
outSink = new StringBuffer();
errorSink = new StringBuffer();
}
/// Base teardown.
_tearDown() {
outSink = savedOutSink;
errorSink = savedErrorSink;
exitCode = savedExitCode;
exitHandler = savedExitHandler;
}
setUp(() => _setUp());
tearDown(() => _tearDown());
group('Bootloader', () {
group('plugin processing', () {
test('bad format', () {
BootLoader loader = new BootLoader();
loader.createImage([
'--options',
path.join(testDirectory, 'data/bad_plugin_options.yaml'),
path.join(testDirectory, 'data/test_file.dart')
]);
expect(
errorSink.toString(),
'Plugin configuration skipped: Unrecognized plugin config '
'format, expected `YamlMap`, got `YamlList` '
'(line 2, column 4)\n');
});
test('plugin config', () {
BootLoader loader = new BootLoader();
Image image = loader.createImage([
'--options',
path.join(testDirectory, 'data/plugin_options.yaml'),
path.join(testDirectory, 'data/test_file.dart')
]);
var plugins = image.config.plugins;
expect(plugins, hasLength(1));
expect(plugins.first.name, 'my_plugin1');
});
group('plugin validation', () {
test('requires class name', () {
expect(
validate(new PluginInfo(
name: 'test_plugin', libraryUri: 'my_package/foo.dart')),
isNotNull);
});
test('requires library URI', () {
expect(
validate(
new PluginInfo(name: 'test_plugin', className: 'MyPlugin')),
isNotNull);
});
test('check', () {
expect(
validate(new PluginInfo(
name: 'test_plugin',
className: 'MyPlugin',
libraryUri: 'my_package/foo.dart')),
isNull);
});
});
});
});
}

View file

@ -7,7 +7,6 @@ library analyzer_cli.test.driver;
import 'dart:io';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/error/codes.dart';
@ -17,7 +16,6 @@ import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:path/path.dart' as path;
import 'package:plugin/plugin.dart';
import 'package:test/test.dart';
import 'package:yaml/src/yaml_node.dart';
@ -53,18 +51,6 @@ main() {
group('Driver', () {
group('options', () {
test('custom processor', () {
Driver driver = new Driver();
TestProcessor processor = new TestProcessor();
driver.userDefinedPlugins = [new TestPlugin(processor)];
driver.start([
'--options',
path.join(testDirectory, 'data/test_options.yaml'),
path.join(testDirectory, 'data/test_file.dart')
]);
expect(processor.options['test_plugin'], isNotNull);
expect(processor.exception, isNull);
});
test('todos', () {
drive('data/file_with_todo.dart');
expect(outSink.toString().contains('[info]'), isFalse);
@ -521,39 +507,6 @@ Map<String, YamlNode> parseOptions(String src) =>
ErrorProcessor processorFor(AnalysisError error) =>
processors.firstWhere((p) => p.appliesTo(error));
class TestPlugin extends Plugin {
TestProcessor processor;
TestPlugin(this.processor);
@override
String get uniqueIdentifier => 'test_plugin.core';
@override
void registerExtensionPoints(RegisterExtensionPoint register) {
// None
}
@override
void registerExtensions(RegisterExtension register) {
register(OPTIONS_PROCESSOR_EXTENSION_POINT_ID, processor);
}
}
class TestProcessor extends OptionsProcessor {
Map<String, Object> options;
Exception exception;
@override
void onError(Exception exception) {
this.exception = exception;
}
@override
void optionsProcessed(AnalysisContext context, Map<String, Object> options) {
this.options = options;
}
}
class TestSource implements Source {
TestSource();

View file

@ -1,93 +0,0 @@
// 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.test.plugin_manager_test;
import 'package:analyzer/src/plugin/plugin_configuration.dart';
import 'package:analyzer_cli/src/plugin/plugin_manager.dart';
import 'package:test/test.dart';
main() {
group('plugin manager tests', () {
test('combine plugin info', () {
PluginInfo localInfo = new PluginInfo(name: 'my_plugin');
PluginInfo manifestInfo = new PluginInfo(
className: 'MyPlugin', libraryUri: 'my_plugin/my_plugin.dart');
PluginInfo merged = combine(localInfo, manifestInfo);
expect(merged.name, equals('my_plugin'));
expect(merged.className, equals('MyPlugin'));
expect(merged.libraryUri, equals('my_plugin/my_plugin.dart'));
});
test('find manifest', () {
const manifestSrc = '''
library_uri: 'my_plugin/my_plugin.dart'
''';
var packageMap = {'my_plugin': new Uri.file('my_plugin')};
PluginManager pm =
new PluginManager(packageMap, 'analyzer', (Uri uri) => manifestSrc);
PluginManifest manifest = pm.findManifest('my_plugin');
expect(manifest, isNotNull);
expect(manifest.plugin.libraryUri, equals('my_plugin/my_plugin.dart'));
});
final plugin1Uri = new Uri.file('my_plugin1');
final plugin2Uri = new Uri.file('my_plugin2');
final plugin3Uri = new Uri.file('my_plugin3');
const serverPluginManifest = '''
library_uri: 'my_plugin2/my_plugin2.dart'
contributes_to: analysis_server
''';
const analyzerPluginManifest = '''
library_uri: 'my_plugin3/my_plugin3.dart'
contributes_to: analyzer
''';
var packageMap = {
'my_plugin': plugin1Uri,
'my_plugin2': plugin2Uri,
'my_plugin3': plugin3Uri
};
var manifestReader = (Uri uri) {
if (uri == plugin2Uri) return serverPluginManifest;
if (uri == plugin3Uri) return analyzerPluginManifest;
return null;
};
test('get plugin details', () {
PluginManager pm =
new PluginManager(packageMap, 'analysis_server', manifestReader);
PluginInfo notFound = new PluginInfo(name: 'my_plugin1');
PluginInfo applicable = new PluginInfo(name: 'my_plugin2');
PluginInfo notApplicable = new PluginInfo(name: 'my_plugin3');
PluginConfig localConfig =
new PluginConfig([notFound, applicable, notApplicable]);
Iterable<PluginDetails> details = pm.getPluginDetails(localConfig);
expect(details, hasLength(3));
List<PluginDetails> plugins = sortByName(details);
expect(plugins[0].plugin.name, equals('my_plugin1'));
expect(plugins[0].status, equals(PluginStatus.NotFound));
expect(plugins[1].plugin.name, equals('my_plugin2'));
expect(
plugins[1].plugin.libraryUri, equals('my_plugin2/my_plugin2.dart'));
expect(plugins[1].status, equals(PluginStatus.Applicable));
expect(plugins[2].plugin.name, equals('my_plugin3'));
expect(plugins[2].status, equals(PluginStatus.NotApplicable));
});
});
}
List<PluginDetails> sortByName(Iterable<PluginDetails> details) =>
details.toList()
..sort((p1, p2) => p1.plugin.name.compareTo(p2.plugin.name));