diff --git a/pkg/analyzer/lib/src/lint/options_rule_validator.dart b/pkg/analyzer/lib/src/lint/options_rule_validator.dart index df08b4bc525..d36b5f62e93 100644 --- a/pkg/analyzer/lib/src/lint/options_rule_validator.dart +++ b/pkg/analyzer/lib/src/lint/options_rule_validator.dart @@ -71,47 +71,55 @@ class LinterRuleOptionsValidator extends OptionsValidator { var node = options.valueAt(linter); if (node is YamlMap) { var rules = node.valueAt(rulesKey); - validateRules(rules, reporter); + _validateRules(rules, reporter); } return errors; } - void validateRules(YamlNode? rules, ErrorReporter reporter) { - if (rules is YamlList) { - final seenRules = {}; + void _validateRules(YamlNode? rules, ErrorReporter reporter) { + final seenRules = {}; - String? findIncompatibleRule(LintRule rule) { - for (var incompatibleRule in rule.incompatibleRules) { - if (seenRules.contains(incompatibleRule)) { - return incompatibleRule; - } + String? findIncompatibleRule(LintRule rule) { + for (var incompatibleRule in rule.incompatibleRules) { + if (seenRules.contains(incompatibleRule)) { + return incompatibleRule; } - return null; + } + return null; + } + + void validateRule(YamlNode node, bool enabled) { + var value = node.value; + if (value == null) return; + + final rule = getRegisteredLint(value); + if (rule == null) { + reporter.reportErrorForSpan(UNDEFINED_LINT_WARNING, node.span, [value]); + return; } - for (var ruleNode in rules.nodes) { - final value = ruleNode.value; - if (value != null) { - final rule = getRegisteredLint(value); - if (rule == null) { - reporter.reportErrorForSpan( - UNDEFINED_LINT_WARNING, ruleNode.span, [value]); - continue; - } - - final incompatibleRule = findIncompatibleRule(rule); - if (incompatibleRule != null) { - reporter.reportErrorForSpan(INCOMPATIBLE_LINT_WARNING, - ruleNode.span, [value, incompatibleRule]); - } else if (!seenRules.add(rule.name)) { - reporter.reportErrorForSpan( - DUPLICATE_RULE_HINT, ruleNode.span, [value]); - } else if (rule.maturity == Maturity.deprecated) { - reporter.reportErrorForSpan( - DEPRECATED_LINT_HINT, ruleNode.span, [value]); - } + if (enabled) { + final incompatibleRule = findIncompatibleRule(rule); + if (incompatibleRule != null) { + reporter.reportErrorForSpan( + INCOMPATIBLE_LINT_WARNING, node.span, [value, incompatibleRule]); + } else if (!seenRules.add(rule.name)) { + reporter.reportErrorForSpan(DUPLICATE_RULE_HINT, node.span, [value]); } } + if (rule.maturity == Maturity.deprecated) { + reporter.reportErrorForSpan(DEPRECATED_LINT_HINT, node.span, [value]); + } + } + + if (rules is YamlList) { + for (var ruleNode in rules.nodes) { + validateRule(ruleNode, true); + } + } else if (rules is YamlMap) { + for (var ruleEntry in rules.nodeMap.entries) { + validateRule(ruleEntry.key, ruleEntry.value.value); + } } } } diff --git a/pkg/analyzer/test/src/options/options_rule_validator_test.dart b/pkg/analyzer/test/src/options/options_rule_validator_test.dart index 506b2b67712..83151ea0be9 100644 --- a/pkg/analyzer/test/src/options/options_rule_validator_test.dart +++ b/pkg/analyzer/test/src/options/options_rule_validator_test.dart @@ -56,6 +56,14 @@ linter: ''', [DEPRECATED_LINT_HINT]); } + test_deprecated_rule_map() { + assertErrors(''' +linter: + rules: + deprecated_lint: false + ''', [DEPRECATED_LINT_HINT]); + } + test_duplicated_rule() { assertErrors(''' linter: @@ -74,6 +82,24 @@ linter: ''', [INCOMPATIBLE_LINT_WARNING]); } + test_incompatible_rule_map() { + assertErrors(''' +linter: + rules: + rule_pos: true + rule_neg: true + ''', [INCOMPATIBLE_LINT_WARNING]); + } + + test_incompatible_rule_map_disabled() { + assertErrors(''' +linter: + rules: + rule_pos: true + rule_neg: false + ''', []); + } + test_stable_rule() { assertErrors(''' linter: @@ -82,6 +108,14 @@ linter: ''', []); } + test_stable_rule_map() { + assertErrors(''' +linter: + rules: + stable_lint: true + ''', []); + } + test_undefined_rule() { assertErrors(''' linter: @@ -89,6 +123,14 @@ linter: - this_rule_does_not_exist ''', [UNDEFINED_LINT_WARNING]); } + + test_undefined_rule_map() { + assertErrors(''' +linter: + rules: + this_rule_does_not_exist: false + ''', [UNDEFINED_LINT_WARNING]); + } } class RuleNeg extends LintRule { @@ -99,6 +141,7 @@ class RuleNeg extends LintRule { description: '', details: '', ); + @override List get incompatibleRules => ['rule_pos']; } @@ -111,6 +154,7 @@ class RulePos extends LintRule { description: '', details: '', ); + @override List get incompatibleRules => ['rule_neg']; } diff --git a/pkg/test_runner/analysis_options.yaml b/pkg/test_runner/analysis_options.yaml index ff809b7f7c3..3f45629968a 100644 --- a/pkg/test_runner/analysis_options.yaml +++ b/pkg/test_runner/analysis_options.yaml @@ -12,7 +12,6 @@ linter: cancel_subscriptions: true comment_references: true directives_ordering: true - invariant_booleans: true omit_local_variable_types: true package_api_docs: true prefer_const_constructors: true