blob: c8c76e3ab1c40550a4453b82df7858f518aaeb03 [file] [log] [blame]
// Copyright (c) 2018, 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/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/analysis_options/error/option_codes.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/options_rule_validator.dart';
import 'package:analyzer/src/string_source.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:yaml/yaml.dart';
import '../../generated/test_support.dart';
import '../diagnostics/analysis_options/analysis_options_test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(OptionsRuleValidatorTest);
defineReflectiveTests(OptionsRuleValidatorIncludedFileTest);
});
}
class DeprecatedLint extends TestLintRule {
DeprecatedLint()
: super(name: 'deprecated_lint', state: RuleState.deprecated());
}
class DeprecatedLintWithReplacement extends TestLintRule {
DeprecatedLintWithReplacement()
: super(
name: 'deprecated_lint_with_replacement',
state: RuleState.deprecated(replacedBy: 'replacing_lint'),
);
}
class DeprecatedSince3Lint extends TestLintRule {
DeprecatedSince3Lint()
: super(
name: 'deprecated_since_3_lint',
state: RuleState.deprecated(since: dart3),
);
}
@reflectiveTest
class OptionsRuleValidatorIncludedFileTest extends AbstractAnalysisOptionsTest
with OptionsRuleValidatorTestMixin {
Future<void> test_deprecated_rule_inInclude_ok() async {
newFile('/included.yaml', '''
linter:
rules:
- deprecated_lint
''');
await assertErrorsInCode('''
include: included.yaml
''', []);
}
Future<void> test_removed_rule_inInclude_ok() async {
newFile('/included.yaml', '''
linter:
rules:
- removed_in_2_12_lint
''');
await assertErrorsInCode('''
include: included.yaml
''', []);
}
}
@reflectiveTest
class OptionsRuleValidatorTest extends AbstractAnalysisOptionsTest
with OptionsRuleValidatorTestMixin {
test_deprecated_rule() {
assertErrors(
'''
linter:
rules:
- deprecated_lint_with_replacement
''',
[AnalysisOptionsWarningCode.DEPRECATED_LINT_WITH_REPLACEMENT],
);
}
test_deprecated_rule_map() {
assertErrors(
'''
linter:
rules:
deprecated_lint: false
''',
[AnalysisOptionsWarningCode.DEPRECATED_LINT],
);
}
test_deprecated_rule_withReplacement() {
assertErrors(
'''
linter:
rules:
- deprecated_lint
''',
[AnalysisOptionsWarningCode.DEPRECATED_LINT],
);
}
test_deprecated_rule_withSince_inCurrentSdk() {
assertErrors(
'''
linter:
rules:
- deprecated_since_3_lint
''',
[AnalysisOptionsWarningCode.DEPRECATED_LINT],
sdk: dart3,
);
}
test_deprecated_rule_withSince_notInCurrentSdk() {
assertErrors(
'''
linter:
rules:
- deprecated_since_3_lint
''',
[],
sdk: Version(2, 17, 0),
);
}
test_deprecated_rule_withSince_unknownSdk() {
assertErrors(
'''
linter:
rules:
- deprecated_since_3_lint
''',
// No error
[],
);
}
test_duplicated_rule() {
assertErrors(
'''
linter:
rules:
- stable_lint
- stable_lint
''',
[AnalysisOptionsWarningCode.DUPLICATE_RULE],
);
}
test_incompatible_rule() {
assertErrors(
'''
linter:
rules:
- rule_pos
- rule_neg
''',
[AnalysisOptionsWarningCode.INCOMPATIBLE_LINT],
);
}
test_incompatible_rule_map() {
assertErrors(
'''
linter:
rules:
rule_pos: true
rule_neg: true
''',
[AnalysisOptionsWarningCode.INCOMPATIBLE_LINT],
);
}
test_incompatible_rule_map_disabled() {
assertErrors('''
linter:
rules:
rule_pos: true
rule_neg: false
''', []);
}
test_removed_rule() {
assertErrors(
'''
linter:
rules:
- removed_in_2_12_lint
''',
[AnalysisOptionsWarningCode.REMOVED_LINT],
sdk: dart2_12,
);
}
test_removed_rule_notYet_ok() {
assertErrors(
'''
linter:
rules:
- removed_in_2_12_lint
''',
[],
sdk: Version(2, 11, 0),
);
}
test_replaced_rule() {
assertErrors(
'''
linter:
rules:
- replaced_lint
''',
[AnalysisOptionsWarningCode.REPLACED_LINT],
sdk: dart3,
);
}
test_stable_rule() {
assertErrors('''
linter:
rules:
- stable_lint
''', []);
}
test_stable_rule_map() {
assertErrors('''
linter:
rules:
stable_lint: true
''', []);
}
test_undefined_rule() {
assertErrors(
'''
linter:
rules:
- this_rule_does_not_exist
''',
[AnalysisOptionsWarningCode.UNDEFINED_LINT],
);
}
test_undefined_rule_map() {
assertErrors(
'''
linter:
rules:
this_rule_does_not_exist: false
''',
[AnalysisOptionsWarningCode.UNDEFINED_LINT],
);
}
}
mixin OptionsRuleValidatorTestMixin on AbstractAnalysisOptionsTest {
/// Assert that when the validator is used on the given [content] the
/// [expectedCodes] are produced.
void assertErrors(
String content,
List<DiagnosticCode> expectedCodes, {
VersionConstraint? sdk,
}) {
GatheringErrorListener listener = GatheringErrorListener();
ErrorReporter reporter = ErrorReporter(
listener,
StringSource(content, 'analysis_options.yaml'),
);
var validator = LinterRuleOptionsValidator(sdkVersionConstraint: sdk);
validator.validate(reporter, loadYamlNode(content) as YamlMap);
listener.assertErrorsWithCodes(expectedCodes);
}
@override
void setUp() {
registerLintRules([
DeprecatedLint(),
DeprecatedSince3Lint(),
DeprecatedLintWithReplacement(),
StableLint(),
RuleNeg(),
RulePos(),
RemovedIn2_12Lint(),
ReplacedLint(),
ReplacingLint(),
]);
super.setUp();
}
}
class RemovedIn2_12Lint extends TestLintRule {
RemovedIn2_12Lint()
: super(
name: 'removed_in_2_12_lint',
state: RuleState.removed(since: dart2_12),
);
}
class ReplacedLint extends TestLintRule {
ReplacedLint()
: super(
name: 'replaced_lint',
state: RuleState.removed(since: dart3, replacedBy: 'replacing_lint'),
);
}
class ReplacingLint extends TestLintRule {
ReplacingLint() : super(name: 'replacing_lint');
}
class RuleNeg extends TestLintRule {
RuleNeg() : super(name: 'rule_neg');
@override
List<String> get incompatibleRules => ['rule_pos'];
}
class RulePos extends TestLintRule {
RulePos() : super(name: 'rule_pos');
@override
List<String> get incompatibleRules => ['rule_neg'];
}
class StableLint extends TestLintRule {
StableLint() : super(name: 'stable_lint', state: RuleState.stable());
}
abstract class TestLintRule extends LintRule {
static const LintCode code = LintCode(
'lint_code',
'Lint code.',
correctionMessage: 'Lint code.',
);
TestLintRule({required super.name, super.state}) : super(description: '');
@override
DiagnosticCode get diagnosticCode => code;
}