blob: e3905715171a6db57cacc94071c3e892b8c068d2 [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.
import 'package:analyzer/src/analysis_options/analysis_options_file.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:yaml/yaml.dart';
/// Returns the [RuleConfig]s that are parsed from [value], which can be either
/// a YAML list or a YAML map, mapped from each rule's name.
Map<String, RuleConfig> parseDiagnosticsSection(YamlNode value) {
// For example:
//
// ```yaml
// - unnecessary_getters
// - camel_case_types
// ```
if (value is YamlList) {
return {
for (var ruleNode in value.nodes)
if (ruleNode case YamlScalar(value: String ruleName))
ruleName: RuleConfig._(
name: ruleName,
severity: ConfiguredSeverity.enable,
),
};
}
if (value is! YamlMap) {
return const {};
}
var ruleConfigs = <String, RuleConfig>{};
value.nodes.forEach((configKey, configValue) {
if (configKey case YamlScalar(value: String configName)) {
var ruleConfig = _parseRuleConfig(configKey, configValue);
if (ruleConfig != null) {
ruleConfigs[ruleConfig.name] = ruleConfig;
return;
}
if (configValue is! YamlMap) {
return;
}
// For example:
//
// ```yaml
// style_guide: {unnecessary_getters: false, camel_case_types: true}
// ```
configValue.nodes.forEach((ruleName, ruleValue) {
var ruleConfig = _parseRuleConfig(
ruleName,
ruleValue,
group: configName,
);
if (ruleConfig != null) {
ruleConfigs[ruleConfig.name] = ruleConfig;
return;
}
});
}
});
return ruleConfigs;
}
/// Parses [optionsMap] into [RuleConfig]s mapped from their names, returning
/// them, or `null` if [optionsMap] does not have `linter` map.
Map<String, RuleConfig>? parseLinterSection(YamlMap optionsMap) {
var options = optionsMap.valueAt('linter');
// Quick check of basic contract.
if (options is YamlMap) {
var rulesNode = options.valueAt(AnalysisOptionsFile.rules);
return {if (rulesNode != null) ...parseDiagnosticsSection(rulesNode)};
}
return null;
}
RuleConfig? _parseRuleConfig(
dynamic configKey,
YamlNode configNode, {
String? group,
}) {
// For example: `{unnecessary_getters: false}`.
if (configKey case YamlScalar(value: String ruleName)) {
if (configNode case YamlScalar(value: bool isEnabled)) {
var severity = isEnabled
? ConfiguredSeverity.enable
: ConfiguredSeverity.disable;
return RuleConfig._(name: ruleName, group: group, severity: severity);
} else if (configNode case YamlScalar(value: String severityString)) {
var severity =
ConfiguredSeverity.values.asNameMap()[severityString] ??
ConfiguredSeverity.enable;
return RuleConfig._(name: ruleName, group: group, severity: severity);
}
}
return null;
}
/// An alias for a [RuleConfig], but which is configured under a 'diagnostics'
/// key in an analysis options file.
///
/// In an analyzer plugin, diagnostics are enabled and disabled via their name.
/// (For the built-in lint diagnostics, which are configured in an analysis
/// options file's top-level 'linter' key, diagnostics are enabled and disabled
/// via the name of the lint rule that reports the diagnostic.)
typedef DiagnosticConfig = RuleConfig;
/// The possible values for an analysis rule's configured severity.
enum ConfiguredSeverity {
/// A severity indicating the rule is simply disabled.
disable,
/// A severity indicating the rule is enabled with its default severity.
enable,
/// A severity indicating the rule is enabled with the 'info' severity.
info,
/// A severity indicating the rule is enabled with the 'warning' severity.
warning,
/// A severity indicating the rule is enabled with the 'error' severity.
error,
}
/// The configuration of a single analysis rule within an analysis options file.
class RuleConfig {
/// The name of the group under which this configuration is found.
final String? group;
/// The name of the rule.
final String name;
/// The rule's severity in this configuration.
final ConfiguredSeverity severity;
RuleConfig._({required this.name, this.group, required this.severity});
/// Whether this rule is enabled or disabled in this configuration.
bool get isEnabled => severity != ConfiguredSeverity.disable;
/// Returns whether [ruleName] is disabled in this configuration.
bool disables(String ruleName) => ruleName == name && !isEnabled;
/// Returns whether [ruleName] is enabled in this configuration.
bool enables(String ruleName) => ruleName == name && isEnabled;
}