Compare commits
6 Commits
brent/lamb
...
zanie/rule
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1880cb45df | ||
|
|
df8a3db939 | ||
|
|
595207b853 | ||
|
|
97654a9911 | ||
|
|
eccda3d3ed | ||
|
|
daa9b4db72 |
@@ -89,3 +89,5 @@ default = []
|
||||
schemars = ["dep:schemars"]
|
||||
# Enables the UnreachableCode rule
|
||||
unreachable-code = []
|
||||
# Enables rules for internal integration tests
|
||||
test-rules = []
|
||||
|
||||
@@ -865,6 +865,13 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||
(Ruff, "017") => (RuleGroup::Nursery, rules::ruff::rules::QuadraticListSummation),
|
||||
(Ruff, "100") => (RuleGroup::Unspecified, rules::ruff::rules::UnusedNOQA),
|
||||
(Ruff, "200") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidPyprojectToml),
|
||||
#[cfg(feature = "test-rules")]
|
||||
(Ruff, "900") => (RuleGroup::Unspecified, rules::ruff::rules::StableTestRule),
|
||||
#[cfg(feature = "test-rules")]
|
||||
(Ruff, "911") => (RuleGroup::Preview, rules::ruff::rules::PreviewTestRule),
|
||||
#[cfg(feature = "test-rules")]
|
||||
#[allow(deprecated)]
|
||||
(Ruff, "912") => (RuleGroup::Nursery, rules::ruff::rules::NurseryTestRule),
|
||||
|
||||
// flake8-django
|
||||
(Flake8Django, "001") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoNullableModelStringField),
|
||||
|
||||
@@ -8,16 +8,6 @@ use itertools::Itertools;
|
||||
use log::error;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_ast::imports::ImportMap;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::lexer::LexResult;
|
||||
use ruff_python_parser::{AsMode, ParseError};
|
||||
use ruff_source_file::{Locator, SourceFileBuilder};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::autofix::{fix_file, FixResult};
|
||||
use crate::checkers::ast::check_ast;
|
||||
use crate::checkers::filesystem::check_file_path;
|
||||
@@ -35,6 +25,15 @@ use crate::rules::pycodestyle;
|
||||
use crate::settings::{flags, Settings};
|
||||
use crate::source_kind::SourceKind;
|
||||
use crate::{directives, fs};
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_ast::imports::ImportMap;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::lexer::LexResult;
|
||||
use ruff_python_parser::{AsMode, ParseError};
|
||||
use ruff_source_file::{Locator, SourceFileBuilder};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const CARGO_PKG_REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY");
|
||||
@@ -213,6 +212,31 @@ pub fn check_path(
|
||||
));
|
||||
}
|
||||
|
||||
// Raise violations for internal test rules
|
||||
#[cfg(feature = "test-rules")]
|
||||
{
|
||||
if settings.rules.enabled(Rule::StableTestRule) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
crate::rules::ruff::rules::StableTestRule,
|
||||
ruff_text_size::TextRange::default(),
|
||||
));
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::PreviewTestRule) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
crate::rules::ruff::rules::PreviewTestRule,
|
||||
ruff_text_size::TextRange::default(),
|
||||
));
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::NurseryTestRule) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
crate::rules::ruff::rules::NurseryTestRule,
|
||||
ruff_text_size::TextRange::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore diagnostics based on per-file-ignores.
|
||||
if !diagnostics.is_empty() && !settings.per_file_ignores.is_empty() {
|
||||
let ignores = fs::ignores_from_path(path, &settings.per_file_ignores);
|
||||
|
||||
@@ -10,6 +10,8 @@ pub(crate) use mutable_class_default::*;
|
||||
pub(crate) use mutable_dataclass_default::*;
|
||||
pub(crate) use pairwise_over_zipped::*;
|
||||
pub(crate) use static_key_dict_comprehension::*;
|
||||
#[cfg(feature = "test-rules")]
|
||||
pub(crate) use test_rules::*;
|
||||
pub(crate) use unnecessary_iterable_allocation_for_first_element::*;
|
||||
#[cfg(feature = "unreachable-code")]
|
||||
pub(crate) use unreachable::*;
|
||||
@@ -29,6 +31,8 @@ mod mutable_class_default;
|
||||
mod mutable_dataclass_default;
|
||||
mod pairwise_over_zipped;
|
||||
mod static_key_dict_comprehension;
|
||||
#[cfg(feature = "test-rules")]
|
||||
mod test_rules;
|
||||
mod unnecessary_iterable_allocation_for_first_element;
|
||||
#[cfg(feature = "unreachable-code")]
|
||||
pub(crate) mod unreachable;
|
||||
|
||||
83
crates/ruff/src/rules/ruff/rules/test_rules.rs
Normal file
83
crates/ruff/src/rules/ruff/rules/test_rules.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use ruff_diagnostics::{AutofixKind, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
/// ## What it does
|
||||
/// Fake rule for testing.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Tests must pass!
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// foo
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// bar
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct StableTestRule;
|
||||
|
||||
impl Violation for StableTestRule {
|
||||
const AUTOFIX: AutofixKind = AutofixKind::None;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Hey this is a stable test rule.")
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Fake rule for testing.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Tests must pass!
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// foo
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// bar
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct PreviewTestRule;
|
||||
|
||||
impl Violation for PreviewTestRule {
|
||||
const AUTOFIX: AutofixKind = AutofixKind::None;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Hey this is a preview test rule.")
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Fake rule for testing.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Tests must pass!
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// foo
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// bar
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct NurseryTestRule;
|
||||
|
||||
impl Violation for NurseryTestRule {
|
||||
const AUTOFIX: AutofixKind = AutofixKind::None;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Hey this is a nursery test rule.")
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ walkdir = { version = "2.3.2" }
|
||||
wild = { version = "2" }
|
||||
|
||||
[dev-dependencies]
|
||||
ruff = { path = "../ruff", features = ["clap", "test-rules"] }
|
||||
assert_cmd = { version = "2.0.8" }
|
||||
# Avoid writing colored snapshots when running tests from the terminal
|
||||
colored = { workspace = true, features = ["no-color"]}
|
||||
|
||||
@@ -249,16 +249,16 @@ fn show_statistics() {
|
||||
|
||||
#[test]
|
||||
fn nursery_prefix() {
|
||||
// `--select E` should detect E741, but not E225, which is in the nursery.
|
||||
let args = ["--select", "E"];
|
||||
// Should only detect RUF900, but not the unstable test rules
|
||||
let args = ["--select", "RUF9"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: E741 Ambiguous variable name: `I`
|
||||
-:1:1: RUF900 Hey this is a stable test rule.
|
||||
Found 1 error.
|
||||
|
||||
----- stderr -----
|
||||
@@ -267,17 +267,17 @@ fn nursery_prefix() {
|
||||
|
||||
#[test]
|
||||
fn nursery_all() {
|
||||
// `--select ALL` should detect E741, but not E225, which is in the nursery.
|
||||
// Should detect RUF900, but not the unstable test rules
|
||||
let args = ["--select", "ALL"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: E741 Ambiguous variable name: `I`
|
||||
-:1:1: D100 Missing docstring in public module
|
||||
-:1:1: RUF900 Hey this is a stable test rule.
|
||||
Found 2 errors.
|
||||
|
||||
----- stderr -----
|
||||
@@ -288,36 +288,35 @@ fn nursery_all() {
|
||||
|
||||
#[test]
|
||||
fn nursery_direct() {
|
||||
// `--select E225` should detect E225.
|
||||
let args = ["--select", "E225"];
|
||||
let args = ["--select", "RUF912"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 1 error.
|
||||
|
||||
----- stderr -----
|
||||
warning: Selection of nursery rule `E225` without the `--preview` flag is deprecated.
|
||||
warning: Selection of nursery rule `RUF912` without the `--preview` flag is deprecated.
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nursery_group_selector() {
|
||||
// Only nursery rules should be detected e.g. E225 and a warning should be displayed
|
||||
// Only nursery rules should be detected e.g. RUF912
|
||||
let args = ["--select", "NURSERY"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: CPY001 Missing copyright notice at top of file
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 2 errors.
|
||||
|
||||
----- stderr -----
|
||||
@@ -327,17 +326,17 @@ fn nursery_group_selector() {
|
||||
|
||||
#[test]
|
||||
fn nursery_group_selector_preview_enabled() {
|
||||
// Only nursery rules should be detected e.g. E225 and a warning should be displayed
|
||||
// A warning should be displayed due to deprecated selector usage
|
||||
let args = ["--select", "NURSERY", "--preview"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: CPY001 Missing copyright notice at top of file
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 2 errors.
|
||||
|
||||
----- stderr -----
|
||||
@@ -347,18 +346,19 @@ fn nursery_group_selector_preview_enabled() {
|
||||
|
||||
#[test]
|
||||
fn preview_enabled_prefix() {
|
||||
// E741 and E225 (preview) should both be detected
|
||||
let args = ["--select", "E", "--preview"];
|
||||
// All the RUF9XX test rules should be triggered
|
||||
let args = ["--select", "RUF9", "--preview"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: E741 Ambiguous variable name: `I`
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
Found 2 errors.
|
||||
-:1:1: RUF900 Hey this is a stable test rule.
|
||||
-:1:1: RUF911 Hey this is a preview test rule.
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 3 errors.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
@@ -370,15 +370,16 @@ fn preview_enabled_all() {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: E741 Ambiguous variable name: `I`
|
||||
-:1:1: D100 Missing docstring in public module
|
||||
-:1:1: CPY001 Missing copyright notice at top of file
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
Found 4 errors.
|
||||
-:1:1: RUF900 Hey this is a stable test rule.
|
||||
-:1:1: RUF911 Hey this is a preview test rule.
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 5 errors.
|
||||
|
||||
----- stderr -----
|
||||
warning: `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible. Ignoring `one-blank-line-before-class`.
|
||||
@@ -388,16 +389,16 @@ fn preview_enabled_all() {
|
||||
|
||||
#[test]
|
||||
fn preview_enabled_direct() {
|
||||
// E225 should be detected without warning
|
||||
let args = ["--select", "E225", "--preview"];
|
||||
// Should be enabled without warning
|
||||
let args = ["--select", "RUF911", "--preview"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
-:1:1: RUF911 Hey this is a preview test rule.
|
||||
Found 1 error.
|
||||
|
||||
----- stderr -----
|
||||
@@ -406,35 +407,35 @@ fn preview_enabled_direct() {
|
||||
|
||||
#[test]
|
||||
fn preview_disabled_direct() {
|
||||
// FURB145 is preview not nursery so selecting should be empty
|
||||
let args = ["--select", "FURB145"];
|
||||
// RUF911 is preview not nursery so selecting should be empty
|
||||
let args = ["--select", "RUF911"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("a = l[:]\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: Selection `FURB145` has no effect because the `--preview` flag was not included.
|
||||
warning: Selection `RUF911` has no effect because the `--preview` flag was not included.
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preview_disabled_prefix_empty() {
|
||||
// Warns that the selection is empty since all of the CPY rules are in preview
|
||||
let args = ["--select", "CPY"];
|
||||
// Warns that the selection is empty since all of the RUF91 rules are in preview
|
||||
let args = ["--select", "RUF91"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: Selection `CPY` has no effect because the `--preview` flag was not included.
|
||||
warning: Selection `RUF91` has no effect because the `--preview` flag was not included.
|
||||
"###);
|
||||
}
|
||||
|
||||
@@ -445,7 +446,7 @@ fn preview_disabled_group_selector() {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -462,13 +463,14 @@ fn preview_enabled_group_selector() {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: CPY001 Missing copyright notice at top of file
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
Found 2 errors.
|
||||
-:1:1: RUF911 Hey this is a preview test rule.
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 3 errors.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
@@ -476,18 +478,19 @@ fn preview_enabled_group_selector() {
|
||||
|
||||
#[test]
|
||||
fn preview_enabled_group_ignore() {
|
||||
// `--select E --ignore PREVIEW` should detect E741 and E225, which is in preview but "E" is more specific.
|
||||
let args = ["--select", "E", "--ignore", "PREVIEW", "--preview"];
|
||||
// Should detect stable and unstable rules, RUF9 is more specific than PREVIEW so ignore has no effect
|
||||
let args = ["--select", "RUF9", "--ignore", "PREVIEW", "--preview"];
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(args)
|
||||
.pass_stdin("I=42\n"), @r###"
|
||||
.pass_stdin(""), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: E741 Ambiguous variable name: `I`
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
Found 2 errors.
|
||||
-:1:1: RUF900 Hey this is a stable test rule.
|
||||
-:1:1: RUF911 Hey this is a preview test rule.
|
||||
-:1:1: RUF912 Hey this is a nursery test rule.
|
||||
Found 3 errors.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
Reference in New Issue
Block a user