Skip to content

Commit

Permalink
Use a derive macro for Violations (#14557)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Waygood <[email protected]>
  • Loading branch information
MichaReiser and AlexWaygood authored Nov 27, 2024
1 parent 6fd10e2 commit 14ba469
Show file tree
Hide file tree
Showing 629 changed files with 2,555 additions and 2,562 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
1. Create a file for your rule (e.g., `crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs`).

1. In that file, define a violation struct (e.g., `pub struct AssertFalse`). You can grep for
`#[violation]` to see examples.
`#[derive(ViolationMetadata)]` to see examples.

1. In that file, define a function that adds the violation to the diagnostic list as appropriate
(e.g., `pub(crate) fn assert_false`) based on whatever inputs are required for the rule (e.g.,
Expand Down
36 changes: 20 additions & 16 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
doc-valid-idents = [
"..",
"CodeQL",
"FastAPI",
"IPython",
"LangChain",
"LibCST",
"McCabe",
"NumPy",
"SCREAMING_SNAKE_CASE",
"SQLAlchemy",
"StackOverflow",
"PyCharm",
"..",
"CodeQL",
"FastAPI",
"IPython",
"LangChain",
"LibCST",
"McCabe",
"NumPy",
"SCREAMING_SNAKE_CASE",
"SQLAlchemy",
"StackOverflow",
"PyCharm",
"SNMPv1",
"SNMPv2",
"SNMPv3",
"PyFlakes"
]

ignore-interior-mutability = [
# Interned is read-only. The wrapped `Rc` never gets updated.
"ruff_formatter::format_element::Interned",
# The expression is read-only.
"ruff_python_ast::hashable::HashableExpr",
# Interned is read-only. The wrapped `Rc` never gets updated.
"ruff_formatter::format_element::Interned",
# The expression is read-only.
"ruff_python_ast::hashable::HashableExpr",
]
2 changes: 1 addition & 1 deletion crates/ruff_diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub use diagnostic::{Diagnostic, DiagnosticKind};
pub use edit::Edit;
pub use fix::{Applicability, Fix, IsolationLevel};
pub use source_map::{SourceMap, SourceMarker};
pub use violation::{AlwaysFixableViolation, FixAvailability, Violation};
pub use violation::{AlwaysFixableViolation, FixAvailability, Violation, ViolationMetadata};

mod diagnostic;
mod edit;
Expand Down
27 changes: 25 additions & 2 deletions crates/ruff_diagnostics/src/violation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::DiagnosticKind;
use std::fmt::{Debug, Display};

#[derive(Debug, Copy, Clone)]
Expand All @@ -17,7 +18,16 @@ impl Display for FixAvailability {
}
}

pub trait Violation: Debug + PartialEq + Eq {
pub trait ViolationMetadata {
/// Returns the rule name of this violation
fn rule_name() -> &'static str;

/// Returns an explanation of what this violation catches,
/// why it's bad, and what users should do instead.
fn explain() -> Option<&'static str>;
}

pub trait Violation: ViolationMetadata {
/// `None` in the case a fix is never available or otherwise Some
/// [`FixAvailability`] describing the available fix.
const FIX_AVAILABILITY: FixAvailability = FixAvailability::None;
Expand All @@ -41,7 +51,7 @@ pub trait Violation: Debug + PartialEq + Eq {

/// This trait exists just to make implementing the [`Violation`] trait more
/// convenient for violations that can always be fixed.
pub trait AlwaysFixableViolation: Debug + PartialEq + Eq {
pub trait AlwaysFixableViolation: ViolationMetadata {
/// The message used to describe the violation.
fn message(&self) -> String;

Expand Down Expand Up @@ -69,3 +79,16 @@ impl<V: AlwaysFixableViolation> Violation for V {
<Self as AlwaysFixableViolation>::message_formats()
}
}

impl<T> From<T> for DiagnosticKind
where
T: Violation,
{
fn from(value: T) -> Self {
Self {
body: Violation::message(&value),
suggestion: Violation::fix_title(&value),
name: T::rule_name().to_string(),
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::Expr;
use ruff_python_ast::{self as ast};
use ruff_python_semantic::Modules;
Expand Down Expand Up @@ -39,8 +39,8 @@ use crate::checkers::ast::Checker;
///
/// dag = DAG(dag_id="my_dag", schedule=timedelta(days=1))
/// ```
#[violation]
pub struct AirflowDagNoScheduleArgument;
#[derive(ViolationMetadata)]
pub(crate) struct AirflowDagNoScheduleArgument;

impl Violation for AirflowDagNoScheduleArgument {
#[derive_message_formats]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast as ast;
use ruff_python_ast::Expr;
use ruff_python_semantic::Modules;
Expand Down Expand Up @@ -31,8 +31,8 @@ use crate::checkers::ast::Checker;
///
/// my_task = PythonOperator(task_id="my_task")
/// ```
#[violation]
pub struct AirflowVariableNameTaskIdMismatch {
#[derive(ViolationMetadata)]
pub(crate) struct AirflowVariableNameTaskIdMismatch {
task_id: String,
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_trivia::CommentRanges;
use ruff_source_file::{LineRanges, UniversalNewlineIterator};
use ruff_text_size::TextRange;
Expand Down Expand Up @@ -29,8 +29,8 @@ use super::super::detection::comment_contains_code;
/// - `lint.task-tags`
///
/// [#4845]: https://github.com/astral-sh/ruff/issues/4845
#[violation]
pub struct CommentedOutCode;
#[derive(ViolationMetadata)]
pub(crate) struct CommentedOutCode;

impl Violation for CommentedOutCode {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::None;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast as ast;
use ruff_python_ast::helpers::map_callable;
use ruff_python_semantic::Modules;
Expand Down Expand Up @@ -63,8 +63,8 @@ use crate::settings::types::PythonVersion;
/// [fastAPI documentation]: https://fastapi.tiangolo.com/tutorial/query-params-str-validations/?h=annotated#advantages-of-annotated
/// [typing.Annotated]: https://docs.python.org/3/library/typing.html#typing.Annotated
/// [typing_extensions]: https://typing-extensions.readthedocs.io/en/stable/
#[violation]
pub struct FastApiNonAnnotatedDependency {
#[derive(ViolationMetadata)]
pub(crate) struct FastApiNonAnnotatedDependency {
py_version: PythonVersion,
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::{Decorator, Expr, ExprCall, Keyword, StmtFunctionDef};
use ruff_python_semantic::{Modules, SemanticModel};
use ruff_text_size::Ranged;
Expand Down Expand Up @@ -59,8 +59,8 @@ use crate::rules::fastapi::rules::is_fastapi_route_decorator;
/// return item
/// ```
#[violation]
pub struct FastApiRedundantResponseModel;
#[derive(ViolationMetadata)]
pub(crate) struct FastApiRedundantResponseModel;

impl AlwaysFixableViolation for FastApiRedundantResponseModel {
#[derive_message_formats]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::str::CharIndices;

use ruff_diagnostics::Fix;
use ruff_diagnostics::{Diagnostic, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast as ast;
use ruff_python_ast::{Expr, Parameter, ParameterWithDefault};
use ruff_python_semantic::{Modules, SemanticModel};
Expand Down Expand Up @@ -62,8 +62,8 @@ use crate::rules::fastapi::rules::is_fastapi_route_decorator;
/// ## Fix safety
/// This rule's fix is marked as unsafe, as modifying a function signature can
/// change the behavior of the code.
#[violation]
pub struct FastApiUnusedPathParameter {
#[derive(ViolationMetadata)]
pub(crate) struct FastApiUnusedPathParameter {
arg_name: String,
function_name: String,
is_positional: bool,
Expand Down
22 changes: 11 additions & 11 deletions crates/ruff_linter/src/rules/flake8_2020/rules/compare.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::{self as ast, CmpOp, Expr};
use ruff_text_size::Ranged;

Expand Down Expand Up @@ -40,8 +40,8 @@ use super::super::helpers::is_sys;
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionCmpStr3;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionCmpStr3;

impl Violation for SysVersionCmpStr3 {
#[derive_message_formats]
Expand Down Expand Up @@ -87,8 +87,8 @@ impl Violation for SysVersionCmpStr3 {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionInfo0Eq3;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionInfo0Eq3;

impl Violation for SysVersionInfo0Eq3 {
#[derive_message_formats]
Expand Down Expand Up @@ -127,8 +127,8 @@ impl Violation for SysVersionInfo0Eq3 {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionInfo1CmpInt;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionInfo1CmpInt;

impl Violation for SysVersionInfo1CmpInt {
#[derive_message_formats]
Expand Down Expand Up @@ -169,8 +169,8 @@ impl Violation for SysVersionInfo1CmpInt {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionInfoMinorCmpInt;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionInfoMinorCmpInt;

impl Violation for SysVersionInfoMinorCmpInt {
#[derive_message_formats]
Expand Down Expand Up @@ -212,8 +212,8 @@ impl Violation for SysVersionInfoMinorCmpInt {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionCmpStr10;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionCmpStr10;

impl Violation for SysVersionCmpStr10 {
#[derive_message_formats]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::Expr;
use ruff_python_semantic::Modules;
use ruff_text_size::Ranged;
Expand Down Expand Up @@ -35,8 +35,8 @@ use crate::checkers::ast::Checker;
/// - [PyPI: `six`](https://pypi.org/project/six/)
/// - [Six documentation: `six.PY2`](https://six.readthedocs.io/#six.PY2)
/// - [Six documentation: `six.PY3`](https://six.readthedocs.io/#six.PY3)
#[violation]
pub struct SixPY3;
#[derive(ViolationMetadata)]
pub(crate) struct SixPY3;

impl Violation for SixPY3 {
#[derive_message_formats]
Expand Down
18 changes: 9 additions & 9 deletions crates/ruff_linter/src/rules/flake8_2020/rules/subscript.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;

Expand Down Expand Up @@ -37,8 +37,8 @@ use crate::rules::flake8_2020::helpers::is_sys;
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionSlice3;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionSlice3;

impl Violation for SysVersionSlice3 {
#[derive_message_formats]
Expand Down Expand Up @@ -77,8 +77,8 @@ impl Violation for SysVersionSlice3 {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersion2;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersion2;

impl Violation for SysVersion2 {
#[derive_message_formats]
Expand Down Expand Up @@ -117,8 +117,8 @@ impl Violation for SysVersion2 {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersion0;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersion0;

impl Violation for SysVersion0 {
#[derive_message_formats]
Expand Down Expand Up @@ -157,8 +157,8 @@ impl Violation for SysVersion0 {
/// ## References
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
#[violation]
pub struct SysVersionSlice1;
#[derive(ViolationMetadata)]
pub(crate) struct SysVersionSlice1;

impl Violation for SysVersionSlice1 {
#[derive_message_formats]
Expand Down
Loading

0 comments on commit 14ba469

Please sign in to comment.