Reduce explcit clones (#3793)

This commit is contained in:
Micha Reiser 2023-03-29 15:15:14 +02:00 committed by GitHub
parent b6f1fed424
commit 595cd065f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 557 additions and 484 deletions

View file

@ -327,7 +327,7 @@ pub fn remove_unused_imports<'a>(
delete_stmt(stmt, parent, deleted, locator, indexer, stylist) delete_stmt(stmt, parent, deleted, locator, indexer, stylist)
} else { } else {
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -655,7 +655,7 @@ where
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(stmt), range: Range::from(stmt),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -853,7 +853,7 @@ where
synthetic_usage: Some((self.ctx.scope_id(), Range::from(alias))), synthetic_usage: Some((self.ctx.scope_id(), Range::from(alias))),
typing_usage: None, typing_usage: None,
range: Range::from(alias), range: Range::from(alias),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -883,7 +883,7 @@ where
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(alias), range: Range::from(alias),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -911,7 +911,7 @@ where
}, },
typing_usage: None, typing_usage: None,
range: Range::from(alias), range: Range::from(alias),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -1157,7 +1157,7 @@ where
synthetic_usage: Some((self.ctx.scope_id(), Range::from(alias))), synthetic_usage: Some((self.ctx.scope_id(), Range::from(alias))),
typing_usage: None, typing_usage: None,
range: Range::from(alias), range: Range::from(alias),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -1191,7 +1191,7 @@ where
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(stmt), range: Range::from(stmt),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -1271,7 +1271,7 @@ where
}, },
typing_usage: None, typing_usage: None,
range: Range::from(alias), range: Range::from(alias),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -1871,7 +1871,7 @@ where
// Recurse. // Recurse.
let prev_in_exception_handler = self.ctx.in_exception_handler; let prev_in_exception_handler = self.ctx.in_exception_handler;
let prev_visible_scope = self.ctx.visible_scope.clone(); let prev_visible_scope = self.ctx.visible_scope;
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { StmtKind::FunctionDef {
body, body,
@ -1891,19 +1891,18 @@ where
flake8_bugbear::rules::f_string_docstring(self, body); flake8_bugbear::rules::f_string_docstring(self, body);
} }
let definition = docstrings::extraction::extract( let definition = docstrings::extraction::extract(
&self.ctx.visible_scope, self.ctx.visible_scope,
stmt, stmt,
body, body,
&Documentable::Function, Documentable::Function,
); );
if self.settings.rules.enabled(Rule::YieldInForLoop) { if self.settings.rules.enabled(Rule::YieldInForLoop) {
pyupgrade::rules::yield_in_for_loop(self, stmt); pyupgrade::rules::yield_in_for_loop(self, stmt);
} }
let scope = let scope = transition_scope(self.ctx.visible_scope, stmt, Documentable::Function);
transition_scope(&self.ctx.visible_scope, stmt, &Documentable::Function);
self.deferred.definitions.push(( self.deferred.definitions.push((
definition, definition,
scope.visibility.clone(), scope.visibility,
(self.ctx.scope_stack.clone(), self.ctx.parents.clone()), (self.ctx.scope_stack.clone(), self.ctx.parents.clone()),
)); ));
self.ctx.visible_scope = scope; self.ctx.visible_scope = scope;
@ -1943,7 +1942,7 @@ where
self.deferred.functions.push(( self.deferred.functions.push((
stmt, stmt,
(self.ctx.scope_stack.clone(), self.ctx.parents.clone()), (self.ctx.scope_stack.clone(), self.ctx.parents.clone()),
self.ctx.visible_scope.clone(), self.ctx.visible_scope,
)); ));
} }
StmtKind::ClassDef { StmtKind::ClassDef {
@ -1958,15 +1957,15 @@ where
flake8_bugbear::rules::f_string_docstring(self, body); flake8_bugbear::rules::f_string_docstring(self, body);
} }
let definition = docstrings::extraction::extract( let definition = docstrings::extraction::extract(
&self.ctx.visible_scope, self.ctx.visible_scope,
stmt, stmt,
body, body,
&Documentable::Class, Documentable::Class,
); );
let scope = transition_scope(&self.ctx.visible_scope, stmt, &Documentable::Class); let scope = transition_scope(self.ctx.visible_scope, stmt, Documentable::Class);
self.deferred.definitions.push(( self.deferred.definitions.push((
definition, definition,
scope.visibility.clone(), scope.visibility,
(self.ctx.scope_stack.clone(), self.ctx.parents.clone()), (self.ctx.scope_stack.clone(), self.ctx.parents.clone()),
)); ));
self.ctx.visible_scope = scope; self.ctx.visible_scope = scope;
@ -2136,7 +2135,7 @@ where
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(stmt), range: Range::from(stmt),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -3928,7 +3927,7 @@ where
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(arg), range: Range::from(arg),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -3972,7 +3971,7 @@ where
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(pattern), range: Range::from(pattern),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -4019,8 +4018,8 @@ impl<'a> Checker<'a> {
let existing = &self.ctx.bindings[existing_binding_index]; let existing = &self.ctx.bindings[existing_binding_index];
let in_current_scope = stack_index == 0; let in_current_scope = stack_index == 0;
if !existing.kind.is_builtin() if !existing.kind.is_builtin()
&& existing.source.as_ref().map_or(true, |left| { && existing.source.map_or(true, |left| {
binding.source.as_ref().map_or(true, |right| { binding.source.map_or(true, |right| {
!branch_detection::different_forks( !branch_detection::different_forks(
left, left,
right, right,
@ -4373,7 +4372,7 @@ impl<'a> Checker<'a> {
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(expr), range: Range::from(expr),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -4394,7 +4393,7 @@ impl<'a> Checker<'a> {
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(expr), range: Range::from(expr),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -4411,7 +4410,7 @@ impl<'a> Checker<'a> {
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(expr), range: Range::from(expr),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -4477,7 +4476,7 @@ impl<'a> Checker<'a> {
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(expr), range: Range::from(expr),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -4494,7 +4493,7 @@ impl<'a> Checker<'a> {
synthetic_usage: None, synthetic_usage: None,
typing_usage: None, typing_usage: None,
range: Range::from(expr), range: Range::from(expr),
source: Some(self.ctx.current_stmt().clone()), source: Some(*self.ctx.current_stmt()),
context: self.ctx.execution_context(), context: self.ctx.execution_context(),
exceptions: self.ctx.exceptions(), exceptions: self.ctx.exceptions(),
}, },
@ -4539,34 +4538,36 @@ impl<'a> Checker<'a> {
}, },
docstring, docstring,
}, },
self.ctx.visible_scope.visibility.clone(), self.ctx.visible_scope.visibility,
(self.ctx.scope_stack.clone(), self.ctx.parents.clone()), (self.ctx.scope_stack.clone(), self.ctx.parents.clone()),
)); ));
docstring.is_some() docstring.is_some()
} }
fn check_deferred_type_definitions(&mut self) { fn check_deferred_type_definitions(&mut self) {
self.deferred.type_definitions.reverse(); while !self.deferred.type_definitions.is_empty() {
while let Some((expr, (in_annotation, in_type_checking_block), (scopes, parents))) = let type_definitions = std::mem::take(&mut self.deferred.type_definitions);
self.deferred.type_definitions.pop() for (expr, (in_annotation, in_type_checking_block), (scopes, parents)) in
{ type_definitions
self.ctx.scope_stack = scopes; {
self.ctx.parents = parents; self.ctx.scope_stack = scopes;
self.ctx.in_annotation = in_annotation; self.ctx.parents = parents;
self.ctx.in_type_checking_block = in_type_checking_block; self.ctx.in_annotation = in_annotation;
self.ctx.in_type_definition = true; self.ctx.in_type_checking_block = in_type_checking_block;
self.ctx.in_deferred_type_definition = true; self.ctx.in_type_definition = true;
self.visit_expr(expr); self.ctx.in_deferred_type_definition = true;
self.ctx.in_deferred_type_definition = false; self.visit_expr(expr);
self.ctx.in_type_definition = false; self.ctx.in_deferred_type_definition = false;
self.ctx.in_type_definition = false;
}
} }
} }
fn check_deferred_string_type_definitions(&mut self, allocator: &'a typed_arena::Arena<Expr>) { fn check_deferred_string_type_definitions(&mut self, allocator: &'a typed_arena::Arena<Expr>) {
let mut type_definitions = std::mem::take(&mut self.deferred.string_type_definitions); while !self.deferred.string_type_definitions.is_empty() {
loop { let type_definitions = std::mem::take(&mut self.deferred.string_type_definitions);
for (range, value, (in_annotation, in_type_checking_block), (scopes, parents)) in for (range, value, (in_annotation, in_type_checking_block), (scopes, parents)) in
type_definitions.into_iter().rev() type_definitions
{ {
if let Ok((expr, kind)) = parse_type_annotation(value, range, self.locator) { if let Ok((expr, kind)) = parse_type_annotation(value, range, self.locator) {
if in_annotation && self.ctx.annotations_future_enabled { if in_annotation && self.ctx.annotations_future_enabled {
@ -4601,100 +4602,125 @@ impl<'a> Checker<'a> {
} }
} }
} }
if self.deferred.string_type_definitions.is_empty() {
break;
}
type_definitions = std::mem::take(&mut self.deferred.string_type_definitions);
} }
} }
fn check_deferred_functions(&mut self) { fn check_deferred_functions(&mut self) {
self.deferred.functions.reverse(); while !self.deferred.functions.is_empty() {
while let Some((stmt, (scopes, parents), visibility)) = self.deferred.functions.pop() { let deferred_functions = std::mem::take(&mut self.deferred.functions);
self.ctx.scope_stack = scopes.clone(); for (stmt, (scopes, parents), visibility) in deferred_functions {
self.ctx.parents = parents.clone(); let scope_snapshot = scopes.snapshot();
self.ctx.visible_scope = visibility; let parents_snapshot = parents.len();
self.ctx.scope_stack = scopes;
self.ctx.parents = parents;
self.ctx.visible_scope = visibility;
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { body, args, .. } StmtKind::FunctionDef { body, args, .. }
| StmtKind::AsyncFunctionDef { body, args, .. } => { | StmtKind::AsyncFunctionDef { body, args, .. } => {
self.visit_arguments(args); self.visit_arguments(args);
self.visit_body(body); self.visit_body(body);
}
_ => {
unreachable!("Expected StmtKind::FunctionDef | StmtKind::AsyncFunctionDef")
}
} }
_ => unreachable!("Expected StmtKind::FunctionDef | StmtKind::AsyncFunctionDef"),
}
self.deferred.assignments.push((scopes, parents)); let mut scopes = std::mem::take(&mut self.ctx.scope_stack);
scopes.restore(scope_snapshot);
let mut parents = std::mem::take(&mut self.ctx.parents);
parents.truncate(parents_snapshot);
self.deferred.assignments.push((scopes, parents));
}
} }
} }
fn check_deferred_lambdas(&mut self) { fn check_deferred_lambdas(&mut self) {
self.deferred.lambdas.reverse(); while !self.deferred.lambdas.is_empty() {
while let Some((expr, (scopes, parents))) = self.deferred.lambdas.pop() { let lambdas = std::mem::take(&mut self.deferred.lambdas);
self.ctx.scope_stack = scopes.clone(); for (expr, (scopes, parents)) in lambdas {
self.ctx.parents = parents.clone(); let scope_snapshot = scopes.snapshot();
let parents_snapshot = parents.len();
if let ExprKind::Lambda { args, body } = &expr.node { self.ctx.scope_stack = scopes;
self.visit_arguments(args); self.ctx.parents = parents;
self.visit_expr(body);
} else { if let ExprKind::Lambda { args, body } = &expr.node {
unreachable!("Expected ExprKind::Lambda"); self.visit_arguments(args);
self.visit_expr(body);
} else {
unreachable!("Expected ExprKind::Lambda");
}
let mut scopes = std::mem::take(&mut self.ctx.scope_stack);
scopes.restore(scope_snapshot);
let mut parents = std::mem::take(&mut self.ctx.parents);
parents.truncate(parents_snapshot);
self.deferred.assignments.push((scopes, parents));
} }
self.deferred.assignments.push((scopes, parents));
} }
} }
fn check_deferred_assignments(&mut self) { fn check_deferred_assignments(&mut self) {
self.deferred.assignments.reverse(); while !self.deferred.assignments.is_empty() {
while let Some((scopes, ..)) = self.deferred.assignments.pop() { let assignments = std::mem::take(&mut self.deferred.assignments);
let mut scopes_iter = scopes.iter(); for (scopes, ..) in assignments {
let scope_index = *scopes_iter.next().unwrap(); let mut scopes_iter = scopes.iter();
let parent_scope_index = *scopes_iter.next().unwrap(); let scope_index = *scopes_iter.next().unwrap();
let parent_scope_index = *scopes_iter.next().unwrap();
// pyflakes // pyflakes
if self.settings.rules.enabled(Rule::UnusedVariable) { if self.settings.rules.enabled(Rule::UnusedVariable) {
pyflakes::rules::unused_variable(self, scope_index); pyflakes::rules::unused_variable(self, scope_index);
} }
if self.settings.rules.enabled(Rule::UnusedAnnotation) { if self.settings.rules.enabled(Rule::UnusedAnnotation) {
pyflakes::rules::unused_annotation(self, scope_index); pyflakes::rules::unused_annotation(self, scope_index);
} }
if !self.is_stub { if !self.is_stub {
// flake8-unused-arguments // flake8-unused-arguments
if self.settings.rules.any_enabled(&[ if self.settings.rules.any_enabled(&[
Rule::UnusedFunctionArgument, Rule::UnusedFunctionArgument,
Rule::UnusedMethodArgument, Rule::UnusedMethodArgument,
Rule::UnusedClassMethodArgument, Rule::UnusedClassMethodArgument,
Rule::UnusedStaticMethodArgument, Rule::UnusedStaticMethodArgument,
Rule::UnusedLambdaArgument, Rule::UnusedLambdaArgument,
]) { ]) {
self.diagnostics self.diagnostics
.extend(flake8_unused_arguments::rules::unused_arguments( .extend(flake8_unused_arguments::rules::unused_arguments(
self, self,
&self.ctx.scopes[parent_scope_index], &self.ctx.scopes[parent_scope_index],
&self.ctx.scopes[scope_index], &self.ctx.scopes[scope_index],
&self.ctx.bindings, &self.ctx.bindings,
)); ));
}
} }
} }
} }
} }
fn check_deferred_for_loops(&mut self) { fn check_deferred_for_loops(&mut self) {
self.deferred.for_loops.reverse(); while !self.deferred.for_loops.is_empty() {
while let Some((stmt, (scopes, parents))) = self.deferred.for_loops.pop() { let for_loops = std::mem::take(&mut self.deferred.for_loops);
self.ctx.scope_stack = scopes.clone();
self.ctx.parents = parents.clone();
if let StmtKind::For { target, body, .. } | StmtKind::AsyncFor { target, body, .. } = for (stmt, (scopes, parents)) in for_loops {
&stmt.node self.ctx.scope_stack = scopes;
{ self.ctx.parents = parents;
if self.settings.rules.enabled(Rule::UnusedLoopControlVariable) {
flake8_bugbear::rules::unused_loop_control_variable(self, stmt, target, body); if let StmtKind::For { target, body, .. }
| StmtKind::AsyncFor { target, body, .. } = &stmt.node
{
if self.settings.rules.enabled(Rule::UnusedLoopControlVariable) {
flake8_bugbear::rules::unused_loop_control_variable(
self, stmt, target, body,
);
}
} else {
unreachable!("Expected ExprKind::Lambda");
} }
} else {
unreachable!("Expected ExprKind::Lambda");
} }
} }
} }
@ -5032,7 +5058,7 @@ impl<'a> Checker<'a> {
) { ) {
Ok(fix) => { Ok(fix) => {
if fix.content.is_empty() || fix.content == "pass" { if fix.content.is_empty() || fix.content == "pass" {
self.deletions.insert(defined_by.clone()); self.deletions.insert(*defined_by);
} }
Some(fix) Some(fix)
} }
@ -5167,181 +5193,182 @@ impl<'a> Checker<'a> {
]); ]);
let mut overloaded_name: Option<String> = None; let mut overloaded_name: Option<String> = None;
self.deferred.definitions.reverse(); while !self.deferred.definitions.is_empty() {
while let Some((definition, visibility, (scopes, parents))) = let definitions = std::mem::take(&mut self.deferred.definitions);
self.deferred.definitions.pop() for (definition, visibility, (scopes, parents)) in definitions {
{ self.ctx.scope_stack = scopes;
self.ctx.scope_stack = scopes.clone(); self.ctx.parents = parents;
self.ctx.parents = parents.clone();
// flake8-annotations // flake8-annotations
if enforce_annotations { if enforce_annotations {
// TODO(charlie): This should be even stricter, in that an overload // TODO(charlie): This should be even stricter, in that an overload
// implementation should come immediately after the overloaded // implementation should come immediately after the overloaded
// interfaces, without any AST nodes in between. Right now, we // interfaces, without any AST nodes in between. Right now, we
// only error when traversing definition boundaries (functions, // only error when traversing definition boundaries (functions,
// classes, etc.). // classes, etc.).
if !overloaded_name.map_or(false, |overloaded_name| { if !overloaded_name.map_or(false, |overloaded_name| {
flake8_annotations::helpers::is_overload_impl( flake8_annotations::helpers::is_overload_impl(
self,
&definition,
&overloaded_name,
)
}) {
self.diagnostics
.extend(flake8_annotations::rules::definition(
self, self,
&definition, &definition,
&visibility, &overloaded_name,
)); )
} }) {
overloaded_name = flake8_annotations::helpers::overloaded_name(self, &definition); self.diagnostics
} .extend(flake8_annotations::rules::definition(
self,
if self.is_stub { &definition,
if self.settings.rules.enabled(Rule::DocstringInStub) { visibility,
flake8_pyi::rules::docstring_in_stubs(self, definition.docstring); ));
} }
} overloaded_name =
flake8_annotations::helpers::overloaded_name(self, &definition);
// pydocstyle
if enforce_docstrings {
if pydocstyle::helpers::should_ignore_definition(
self,
&definition,
&self.settings.pydocstyle.ignore_decorators,
) {
continue;
} }
if definition.docstring.is_none() { if self.is_stub {
pydocstyle::rules::not_missing(self, &definition, &visibility); if self.settings.rules.enabled(Rule::DocstringInStub) {
continue; flake8_pyi::rules::docstring_in_stubs(self, definition.docstring);
}
} }
// Extract a `Docstring` from a `Definition`. // pydocstyle
let expr = definition.docstring.unwrap(); if enforce_docstrings {
let contents = self.locator.slice(expr); if pydocstyle::helpers::should_ignore_definition(
let indentation = self.locator.slice(Range::new( self,
Location::new(expr.location.row(), 0), &definition,
Location::new(expr.location.row(), expr.location.column()), &self.settings.pydocstyle.ignore_decorators,
)); ) {
continue;
}
if pydocstyle::helpers::should_ignore_docstring(contents) { if definition.docstring.is_none() {
warn_user!( pydocstyle::rules::not_missing(self, &definition, visibility);
continue;
}
// Extract a `Docstring` from a `Definition`.
let expr = definition.docstring.unwrap();
let contents = self.locator.slice(expr);
let indentation = self.locator.slice(Range::new(
Location::new(expr.location.row(), 0),
Location::new(expr.location.row(), expr.location.column()),
));
if pydocstyle::helpers::should_ignore_docstring(contents) {
warn_user!(
"Docstring at {}:{}:{} contains implicit string concatenation; ignoring...", "Docstring at {}:{}:{} contains implicit string concatenation; ignoring...",
relativize_path(self.path), relativize_path(self.path),
expr.location.row(), expr.location.row(),
expr.location.column() + 1 expr.location.column() + 1
); );
continue; continue;
} }
// SAFETY: Safe for docstrings that pass `should_ignore_docstring`. // SAFETY: Safe for docstrings that pass `should_ignore_docstring`.
let body = str::raw_contents(contents).unwrap(); let body = str::raw_contents(contents).unwrap();
let docstring = Docstring { let docstring = Docstring {
kind: definition.kind, kind: definition.kind,
expr, expr,
contents, contents,
indentation, indentation,
body, body,
}; };
if !pydocstyle::rules::not_empty(self, &docstring) { if !pydocstyle::rules::not_empty(self, &docstring) {
continue; continue;
} }
if self.settings.rules.enabled(Rule::FitsOnOneLine) { if self.settings.rules.enabled(Rule::FitsOnOneLine) {
pydocstyle::rules::one_liner(self, &docstring); pydocstyle::rules::one_liner(self, &docstring);
} }
if self.settings.rules.any_enabled(&[ if self.settings.rules.any_enabled(&[
Rule::NoBlankLineBeforeFunction, Rule::NoBlankLineBeforeFunction,
Rule::NoBlankLineAfterFunction, Rule::NoBlankLineAfterFunction,
]) { ]) {
pydocstyle::rules::blank_before_after_function(self, &docstring); pydocstyle::rules::blank_before_after_function(self, &docstring);
} }
if self.settings.rules.any_enabled(&[ if self.settings.rules.any_enabled(&[
Rule::OneBlankLineBeforeClass, Rule::OneBlankLineBeforeClass,
Rule::OneBlankLineAfterClass, Rule::OneBlankLineAfterClass,
Rule::BlankLineBeforeClass, Rule::BlankLineBeforeClass,
]) { ]) {
pydocstyle::rules::blank_before_after_class(self, &docstring); pydocstyle::rules::blank_before_after_class(self, &docstring);
} }
if self.settings.rules.enabled(Rule::BlankLineAfterSummary) { if self.settings.rules.enabled(Rule::BlankLineAfterSummary) {
pydocstyle::rules::blank_after_summary(self, &docstring); pydocstyle::rules::blank_after_summary(self, &docstring);
} }
if self.settings.rules.any_enabled(&[ if self.settings.rules.any_enabled(&[
Rule::IndentWithSpaces, Rule::IndentWithSpaces,
Rule::UnderIndentation, Rule::UnderIndentation,
Rule::OverIndentation, Rule::OverIndentation,
]) { ]) {
pydocstyle::rules::indent(self, &docstring); pydocstyle::rules::indent(self, &docstring);
} }
if self.settings.rules.enabled(Rule::NewLineAfterLastParagraph) { if self.settings.rules.enabled(Rule::NewLineAfterLastParagraph) {
pydocstyle::rules::newline_after_last_paragraph(self, &docstring); pydocstyle::rules::newline_after_last_paragraph(self, &docstring);
} }
if self.settings.rules.enabled(Rule::SurroundingWhitespace) { if self.settings.rules.enabled(Rule::SurroundingWhitespace) {
pydocstyle::rules::no_surrounding_whitespace(self, &docstring); pydocstyle::rules::no_surrounding_whitespace(self, &docstring);
} }
if self.settings.rules.any_enabled(&[ if self.settings.rules.any_enabled(&[
Rule::MultiLineSummaryFirstLine, Rule::MultiLineSummaryFirstLine,
Rule::MultiLineSummarySecondLine, Rule::MultiLineSummarySecondLine,
]) { ]) {
pydocstyle::rules::multi_line_summary_start(self, &docstring); pydocstyle::rules::multi_line_summary_start(self, &docstring);
} }
if self.settings.rules.enabled(Rule::TripleSingleQuotes) { if self.settings.rules.enabled(Rule::TripleSingleQuotes) {
pydocstyle::rules::triple_quotes(self, &docstring); pydocstyle::rules::triple_quotes(self, &docstring);
} }
if self.settings.rules.enabled(Rule::EscapeSequenceInDocstring) { if self.settings.rules.enabled(Rule::EscapeSequenceInDocstring) {
pydocstyle::rules::backslashes(self, &docstring); pydocstyle::rules::backslashes(self, &docstring);
} }
if self.settings.rules.enabled(Rule::EndsInPeriod) { if self.settings.rules.enabled(Rule::EndsInPeriod) {
pydocstyle::rules::ends_with_period(self, &docstring); pydocstyle::rules::ends_with_period(self, &docstring);
} }
if self.settings.rules.enabled(Rule::NonImperativeMood) { if self.settings.rules.enabled(Rule::NonImperativeMood) {
pydocstyle::rules::non_imperative_mood( pydocstyle::rules::non_imperative_mood(
self, self,
&docstring, &docstring,
&self.settings.pydocstyle.property_decorators, &self.settings.pydocstyle.property_decorators,
); );
} }
if self.settings.rules.enabled(Rule::NoSignature) { if self.settings.rules.enabled(Rule::NoSignature) {
pydocstyle::rules::no_signature(self, &docstring); pydocstyle::rules::no_signature(self, &docstring);
} }
if self.settings.rules.enabled(Rule::FirstLineCapitalized) { if self.settings.rules.enabled(Rule::FirstLineCapitalized) {
pydocstyle::rules::capitalized(self, &docstring); pydocstyle::rules::capitalized(self, &docstring);
} }
if self.settings.rules.enabled(Rule::DocstringStartsWithThis) { if self.settings.rules.enabled(Rule::DocstringStartsWithThis) {
pydocstyle::rules::starts_with_this(self, &docstring); pydocstyle::rules::starts_with_this(self, &docstring);
} }
if self.settings.rules.enabled(Rule::EndsInPunctuation) { if self.settings.rules.enabled(Rule::EndsInPunctuation) {
pydocstyle::rules::ends_with_punctuation(self, &docstring); pydocstyle::rules::ends_with_punctuation(self, &docstring);
} }
if self.settings.rules.enabled(Rule::OverloadWithDocstring) { if self.settings.rules.enabled(Rule::OverloadWithDocstring) {
pydocstyle::rules::if_needed(self, &docstring); pydocstyle::rules::if_needed(self, &docstring);
} }
if self.settings.rules.any_enabled(&[ if self.settings.rules.any_enabled(&[
Rule::MultiLineSummaryFirstLine, Rule::MultiLineSummaryFirstLine,
Rule::SectionNotOverIndented, Rule::SectionNotOverIndented,
Rule::SectionUnderlineNotOverIndented, Rule::SectionUnderlineNotOverIndented,
Rule::CapitalizeSectionName, Rule::CapitalizeSectionName,
Rule::NewLineAfterSectionName, Rule::NewLineAfterSectionName,
Rule::DashedUnderlineAfterSection, Rule::DashedUnderlineAfterSection,
Rule::SectionUnderlineAfterName, Rule::SectionUnderlineAfterName,
Rule::SectionUnderlineMatchesSectionLength, Rule::SectionUnderlineMatchesSectionLength,
Rule::NoBlankLineAfterSection, Rule::NoBlankLineAfterSection,
Rule::NoBlankLineBeforeSection, Rule::NoBlankLineBeforeSection,
Rule::BlankLinesBetweenHeaderAndContent, Rule::BlankLinesBetweenHeaderAndContent,
Rule::BlankLineAfterLastSection, Rule::BlankLineAfterLastSection,
Rule::EmptyDocstringSection, Rule::EmptyDocstringSection,
Rule::SectionNameEndsInColon, Rule::SectionNameEndsInColon,
Rule::UndocumentedParam, Rule::UndocumentedParam,
]) { ]) {
pydocstyle::rules::sections( pydocstyle::rules::sections(
self, self,
&docstring, &docstring,
self.settings.pydocstyle.convention.as_ref(), self.settings.pydocstyle.convention.as_ref(),
); );
}
} }
} }
} }

View file

@ -29,12 +29,13 @@ pub struct Docstring<'a> {
pub indentation: &'a str, pub indentation: &'a str,
} }
#[derive(Copy, Clone)]
pub enum Documentable { pub enum Documentable {
Class, Class,
Function, Function,
} }
pub fn transition_scope(scope: &VisibleScope, stmt: &Stmt, kind: &Documentable) -> VisibleScope { pub fn transition_scope(scope: VisibleScope, stmt: &Stmt, kind: Documentable) -> VisibleScope {
match kind { match kind {
Documentable::Function => VisibleScope { Documentable::Function => VisibleScope {
modifier: Modifier::Function, modifier: Modifier::Function,

View file

@ -28,10 +28,10 @@ pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> {
/// Extract a `Definition` from the AST node defined by a `Stmt`. /// Extract a `Definition` from the AST node defined by a `Stmt`.
pub fn extract<'a>( pub fn extract<'a>(
scope: &VisibleScope, scope: VisibleScope,
stmt: &'a Stmt, stmt: &'a Stmt,
body: &'a [Stmt], body: &'a [Stmt],
kind: &Documentable, kind: Documentable,
) -> Definition<'a> { ) -> Definition<'a> {
let expr = docstring_from(body); let expr = docstring_from(body);
match kind { match kind {

View file

@ -129,7 +129,7 @@ pub(crate) struct SectionContext<'a> {
pub(crate) original_index: usize, pub(crate) original_index: usize,
} }
fn suspected_as_section(line: &str, style: &SectionStyle) -> Option<SectionKind> { fn suspected_as_section(line: &str, style: SectionStyle) -> Option<SectionKind> {
if let Some(kind) = SectionKind::from_str(whitespace::leading_words(line)) { if let Some(kind) = SectionKind::from_str(whitespace::leading_words(line)) {
if style.sections().contains(&kind) { if style.sections().contains(&kind) {
return Some(kind); return Some(kind);
@ -168,7 +168,7 @@ fn is_docstring_section(context: &SectionContext) -> bool {
/// Extract all `SectionContext` values from a docstring. /// Extract all `SectionContext` values from a docstring.
pub(crate) fn section_contexts<'a>( pub(crate) fn section_contexts<'a>(
lines: &'a [&'a str], lines: &'a [&'a str],
style: &SectionStyle, style: SectionStyle,
) -> Vec<SectionContext<'a>> { ) -> Vec<SectionContext<'a>> {
let mut contexts = vec![]; let mut contexts = vec![];
for (kind, lineno) in lines for (kind, lineno) in lines

View file

@ -2,6 +2,7 @@ use crate::docstrings::google::GOOGLE_SECTIONS;
use crate::docstrings::numpy::NUMPY_SECTIONS; use crate::docstrings::numpy::NUMPY_SECTIONS;
use crate::docstrings::sections::SectionKind; use crate::docstrings::sections::SectionKind;
#[derive(Copy, Clone)]
pub(crate) enum SectionStyle { pub(crate) enum SectionStyle {
Numpy, Numpy,
Google, Google,

View file

@ -416,7 +416,7 @@ pub fn convert(
if let Some(src_paths) = &isort.src_paths { if let Some(src_paths) = &isort.src_paths {
match options.src.as_mut() { match options.src.as_mut() {
Some(src) => { Some(src) => {
src.extend(src_paths.clone()); src.extend_from_slice(src_paths);
} }
None => { None => {
options.src = Some(src_paths.clone()); options.src = Some(src_paths.clone());

View file

@ -54,7 +54,7 @@ struct Token {
src: String, src: String,
} }
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
enum TokenType { enum TokenType {
Code, Code,
File, File,

View file

@ -7,7 +7,7 @@ use anyhow::anyhow;
use crate::registry::Linter; use crate::registry::Linter;
use crate::rule_selector::RuleSelector; use crate::rule_selector::RuleSelector;
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Plugin { pub enum Plugin {
Flake82020, Flake82020,
Flake8Annotations, Flake8Annotations,

View file

@ -226,7 +226,7 @@ pub enum CodemirrorMode {
} }
/// String identifying the type of cell. /// String identifying the type of cell.
#[derive(Debug, Serialize, Deserialize, PartialEq)] #[derive(Debug, Serialize, Deserialize, PartialEq, Copy, Clone)]
pub enum CellType { pub enum CellType {
#[serde(rename = "code")] #[serde(rename = "code")]
Code, Code,
@ -236,14 +236,14 @@ pub enum CellType {
Raw, Raw,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Copy, Clone)]
pub enum ScrolledEnum { pub enum ScrolledEnum {
#[serde(rename = "auto")] #[serde(rename = "auto")]
Auto, Auto,
} }
/// Type of cell output. /// Type of cell output.
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Copy, Clone)]
pub enum OutputType { pub enum OutputType {
#[serde(rename = "display_data")] #[serde(rename = "display_data")]
DisplayData, DisplayData,

View file

@ -6,7 +6,7 @@
use rustpython_parser::Tok; use rustpython_parser::Tok;
#[derive(Default)] #[derive(Default, Copy, Clone)]
enum State { enum State {
// Start of the module: first string gets marked as a docstring. // Start of the module: first string gets marked as a docstring.
#[default] #[default]

View file

@ -188,7 +188,7 @@ pub fn add_noqa(
contents: &str, contents: &str,
commented_lines: &[usize], commented_lines: &[usize],
noqa_line_for: &IntMap<usize, usize>, noqa_line_for: &IntMap<usize, usize>,
line_ending: &LineEnding, line_ending: LineEnding,
) -> Result<usize> { ) -> Result<usize> {
let (count, output) = add_noqa_inner( let (count, output) = add_noqa_inner(
diagnostics, diagnostics,
@ -206,7 +206,7 @@ fn add_noqa_inner(
contents: &str, contents: &str,
commented_lines: &[usize], commented_lines: &[usize],
noqa_line_for: &IntMap<usize, usize>, noqa_line_for: &IntMap<usize, usize>,
line_ending: &LineEnding, line_ending: LineEnding,
) -> (usize, String) { ) -> (usize, String) {
// Map of line number to set of (non-ignored) diagnostic codes that are triggered on that line. // Map of line number to set of (non-ignored) diagnostic codes that are triggered on that line.
let mut matches_by_line: FxHashMap<usize, RuleSet> = FxHashMap::default(); let mut matches_by_line: FxHashMap<usize, RuleSet> = FxHashMap::default();
@ -288,7 +288,7 @@ fn add_noqa_inner(
match matches_by_line.get(&lineno) { match matches_by_line.get(&lineno) {
None => { None => {
output.push_str(line); output.push_str(line);
output.push_str(line_ending); output.push_str(&line_ending);
} }
Some(rules) => { Some(rules) => {
match extract_noqa_directive(line) { match extract_noqa_directive(line) {
@ -301,13 +301,13 @@ fn add_noqa_inner(
// Add codes. // Add codes.
push_codes(&mut output, rules.iter().map(|rule| rule.noqa_code())); push_codes(&mut output, rules.iter().map(|rule| rule.noqa_code()));
output.push_str(line_ending); output.push_str(&line_ending);
count += 1; count += 1;
} }
Directive::All(..) => { Directive::All(..) => {
// Leave the line as-is. // Leave the line as-is.
output.push_str(line); output.push_str(line);
output.push_str(line_ending); output.push_str(&line_ending);
} }
Directive::Codes(_, start_byte, _, existing, _) => { Directive::Codes(_, start_byte, _, existing, _) => {
// Reconstruct the line based on the preserved rule codes. // Reconstruct the line based on the preserved rule codes.
@ -331,7 +331,7 @@ fn add_noqa_inner(
); );
output.push_str(&formatted); output.push_str(&formatted);
output.push_str(line_ending); output.push_str(&line_ending);
// Only count if the new line is an actual edit. // Only count if the new line is an actual edit.
if formatted != line { if formatted != line {
@ -395,7 +395,7 @@ mod tests {
contents, contents,
&commented_lines, &commented_lines,
&noqa_line_for, &noqa_line_for,
&LineEnding::Lf, LineEnding::Lf,
); );
assert_eq!(count, 0); assert_eq!(count, 0);
assert_eq!(output, format!("{contents}\n")); assert_eq!(output, format!("{contents}\n"));
@ -414,7 +414,7 @@ mod tests {
contents, contents,
&commented_lines, &commented_lines,
&noqa_line_for, &noqa_line_for,
&LineEnding::Lf, LineEnding::Lf,
); );
assert_eq!(count, 1); assert_eq!(count, 1);
assert_eq!(output, "x = 1 # noqa: F841\n"); assert_eq!(output, "x = 1 # noqa: F841\n");
@ -439,7 +439,7 @@ mod tests {
contents, contents,
&commented_lines, &commented_lines,
&noqa_line_for, &noqa_line_for,
&LineEnding::Lf, LineEnding::Lf,
); );
assert_eq!(count, 1); assert_eq!(count, 1);
assert_eq!(output, "x = 1 # noqa: E741, F841\n"); assert_eq!(output, "x = 1 # noqa: E741, F841\n");
@ -464,7 +464,7 @@ mod tests {
contents, contents,
&commented_lines, &commented_lines,
&noqa_line_for, &noqa_line_for,
&LineEnding::Lf, LineEnding::Lf,
); );
assert_eq!(count, 0); assert_eq!(count, 0);
assert_eq!(output, "x = 1 # noqa\n"); assert_eq!(output, "x = 1 # noqa\n");

View file

@ -41,6 +41,7 @@ impl PyprojectDiscovery {
} }
/// The strategy for resolving file paths in a `pyproject.toml`. /// The strategy for resolving file paths in a `pyproject.toml`.
#[derive(Copy, Clone)]
pub enum Relativity { pub enum Relativity {
/// Resolve file paths relative to the current working directory. /// Resolve file paths relative to the current working directory.
Cwd, Cwd,

View file

@ -265,7 +265,7 @@ impl RuleSelector {
} }
} }
#[derive(EnumIter, PartialEq, Eq, PartialOrd, Ord)] #[derive(EnumIter, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub(crate) enum Specificity { pub(crate) enum Specificity {
All, All,
LinterGroup, LinterGroup,

View file

@ -455,7 +455,7 @@ fn check_dynamically_typed<F>(
pub fn definition( pub fn definition(
checker: &Checker, checker: &Checker,
definition: &Definition, definition: &Definition,
visibility: &Visibility, visibility: Visibility,
) -> Vec<Diagnostic> { ) -> Vec<Diagnostic> {
// TODO(charlie): Consider using the AST directly here rather than `Definition`. // TODO(charlie): Consider using the AST directly here rather than `Definition`.
// We could adhere more closely to `flake8-annotations` by defining public // We could adhere more closely to `flake8-annotations` by defining public

View file

@ -7,7 +7,7 @@ use ruff_python_ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Kind { pub enum Kind {
Expression, Expression,
Attribute, Attribute,

View file

@ -61,7 +61,7 @@ pub fn fix_unnecessary_generator_list(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -108,7 +108,7 @@ pub fn fix_unnecessary_generator_set(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -182,7 +182,7 @@ pub fn fix_unnecessary_generator_dict(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -237,7 +237,7 @@ pub fn fix_unnecessary_list_comprehension_set(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -293,7 +293,7 @@ pub fn fix_unnecessary_list_comprehension_dict(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -387,7 +387,7 @@ pub fn fix_unnecessary_literal_set(
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -460,7 +460,7 @@ pub fn fix_unnecessary_literal_dict(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -576,7 +576,7 @@ pub fn fix_unnecessary_collection_call(
}; };
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -635,7 +635,7 @@ pub fn fix_unnecessary_literal_within_tuple_call(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -696,7 +696,7 @@ pub fn fix_unnecessary_literal_within_list_call(
})); }));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -725,7 +725,7 @@ pub fn fix_unnecessary_list_call(
body.value = arg.value.clone(); body.value = arg.value.clone();
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -854,7 +854,7 @@ pub fn fix_unnecessary_call_around_sorted(
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -893,7 +893,7 @@ pub fn fix_unnecessary_double_cast_or_process(
outer_call.args = inner_call.clone(); outer_call.args = inner_call.clone();
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -989,7 +989,7 @@ pub fn fix_unnecessary_comprehension(
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -1142,7 +1142,7 @@ pub fn fix_unnecessary_map(
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -1,4 +1,4 @@
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum DebuggerUsingType { pub enum DebuggerUsingType {
Call(String), Call(String),
Import(String), Import(String),

View file

@ -125,6 +125,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
} }
} }
#[derive(Copy, Clone)]
enum LoggingCallType { enum LoggingCallType {
/// Logging call with a level method, e.g., `logging.info`. /// Logging call with a level method, e.g., `logging.info`.
LevelCall(LoggingLevel), LevelCall(LoggingLevel),

View file

@ -36,7 +36,7 @@ pub fn fix_unnecessary_comprehension_any_all(
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -8,7 +8,7 @@ use ruff_python_ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum VarKind { pub enum VarKind {
TypeVar, TypeVar,
ParamSpec, ParamSpec,

View file

@ -247,6 +247,7 @@ pub fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec<Diagnostic
.collect() .collect()
} }
#[derive(Copy, Clone)]
enum CompositionKind { enum CompositionKind {
// E.g., `a or b or c`. // E.g., `a or b or c`.
None, None,
@ -405,7 +406,7 @@ fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) ->
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -11,6 +11,7 @@ use ruff_python_ast::helpers::{create_expr, create_stmt};
/// An enum to represent the different types of assertions present in the /// An enum to represent the different types of assertions present in the
/// `unittest` module. Note: any variants that can't be replaced with plain /// `unittest` module. Note: any variants that can't be replaced with plain
/// `assert` statements are commented out. /// `assert` statements are commented out.
#[derive(Copy, Clone)]
pub enum UnittestAssert { pub enum UnittestAssert {
AlmostEqual, AlmostEqual,
AlmostEquals, AlmostEquals,
@ -258,7 +259,7 @@ impl UnittestAssert {
Ok(args_map) Ok(args_map)
} }
pub fn generate_assert(&self, args: &[Expr], keywords: &[Keyword]) -> Result<Stmt> { pub fn generate_assert(self, args: &[Expr], keywords: &[Keyword]) -> Result<Stmt> {
let args = self.args_map(args, keywords)?; let args = self.args_map(args, keywords)?;
match self { match self {
UnittestAssert::True | UnittestAssert::False => { UnittestAssert::True | UnittestAssert::False => {

View file

@ -185,35 +185,35 @@ impl AlwaysAutofixableViolation for AvoidableEscapedQuote {
} }
} }
const fn good_single(quote: &Quote) -> char { const fn good_single(quote: Quote) -> char {
match quote { match quote {
Quote::Single => '\'', Quote::Single => '\'',
Quote::Double => '"', Quote::Double => '"',
} }
} }
const fn bad_single(quote: &Quote) -> char { const fn bad_single(quote: Quote) -> char {
match quote { match quote {
Quote::Double => '\'', Quote::Double => '\'',
Quote::Single => '"', Quote::Single => '"',
} }
} }
const fn good_multiline(quote: &Quote) -> &str { const fn good_multiline(quote: Quote) -> &'static str {
match quote { match quote {
Quote::Single => "'''", Quote::Single => "'''",
Quote::Double => "\"\"\"", Quote::Double => "\"\"\"",
} }
} }
const fn good_multiline_ending(quote: &Quote) -> &str { const fn good_multiline_ending(quote: Quote) -> &'static str {
match quote { match quote {
Quote::Single => "'\"\"\"", Quote::Single => "'\"\"\"",
Quote::Double => "\"'''", Quote::Double => "\"'''",
} }
} }
const fn good_docstring(quote: &Quote) -> &str { const fn good_docstring(quote: Quote) -> &'static str {
match quote { match quote {
Quote::Single => "'", Quote::Single => "'",
Quote::Double => "\"", Quote::Double => "\"",
@ -270,21 +270,21 @@ fn docstring(
if trivia if trivia
.raw_text .raw_text
.contains(good_docstring(&quotes_settings.docstring_quotes)) .contains(good_docstring(quotes_settings.docstring_quotes))
{ {
return None; return None;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
BadQuotesDocstring { BadQuotesDocstring {
quote: quotes_settings.docstring_quotes.clone(), quote: quotes_settings.docstring_quotes,
}, },
Range::new(start, end), Range::new(start, end),
); );
if autofix.into() && settings.rules.should_fix(Rule::BadQuotesDocstring) { if autofix.into() && settings.rules.should_fix(Rule::BadQuotesDocstring) {
let quote_count = if trivia.is_multiline { 3 } else { 1 }; let quote_count = if trivia.is_multiline { 3 } else { 1 };
let string_contents = &trivia.raw_text[quote_count..trivia.raw_text.len() - quote_count]; let string_contents = &trivia.raw_text[quote_count..trivia.raw_text.len() - quote_count];
let quote = good_docstring(&quotes_settings.docstring_quotes).repeat(quote_count); let quote = good_docstring(quotes_settings.docstring_quotes).repeat(quote_count);
let mut fixed_contents = let mut fixed_contents =
String::with_capacity(trivia.prefix.len() + string_contents.len() + quote.len() * 2); String::with_capacity(trivia.prefix.len() + string_contents.len() + quote.len() * 2);
fixed_contents.push_str(trivia.prefix); fixed_contents.push_str(trivia.prefix);
@ -323,12 +323,12 @@ fn strings(
return false; return false;
} }
if trivia.last_quote_char == good_single(&quotes_settings.inline_quotes) { if trivia.last_quote_char == good_single(quotes_settings.inline_quotes) {
return false; return false;
} }
let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1]; let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1];
string_contents.contains(good_single(&quotes_settings.inline_quotes)) string_contents.contains(good_single(quotes_settings.inline_quotes))
}); });
for ((start, end), trivia) in sequence.iter().zip(trivia.into_iter()) { for ((start, end), trivia) in sequence.iter().zip(trivia.into_iter()) {
@ -336,7 +336,7 @@ fn strings(
// If our string is or contains a known good string, ignore it. // If our string is or contains a known good string, ignore it.
if trivia if trivia
.raw_text .raw_text
.contains(good_multiline(&quotes_settings.multiline_quotes)) .contains(good_multiline(quotes_settings.multiline_quotes))
{ {
continue; continue;
} }
@ -344,21 +344,21 @@ fn strings(
// If our string ends with a known good ending, then ignore it. // If our string ends with a known good ending, then ignore it.
if trivia if trivia
.raw_text .raw_text
.ends_with(good_multiline_ending(&quotes_settings.multiline_quotes)) .ends_with(good_multiline_ending(quotes_settings.multiline_quotes))
{ {
continue; continue;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
BadQuotesMultilineString { BadQuotesMultilineString {
quote: quotes_settings.multiline_quotes.clone(), quote: quotes_settings.multiline_quotes,
}, },
Range::new(*start, *end), Range::new(*start, *end),
); );
if autofix.into() && settings.rules.should_fix(Rule::BadQuotesMultilineString) { if autofix.into() && settings.rules.should_fix(Rule::BadQuotesMultilineString) {
let string_contents = &trivia.raw_text[3..trivia.raw_text.len() - 3]; let string_contents = &trivia.raw_text[3..trivia.raw_text.len() - 3];
let quote = good_multiline(&quotes_settings.multiline_quotes); let quote = good_multiline(quotes_settings.multiline_quotes);
let mut fixed_contents = String::with_capacity( let mut fixed_contents = String::with_capacity(
trivia.prefix.len() + string_contents.len() + quote.len() * 2, trivia.prefix.len() + string_contents.len() + quote.len() * 2,
); );
@ -373,7 +373,7 @@ fn strings(
let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1]; let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1];
// If we're using the preferred quotation type, check for escapes. // If we're using the preferred quotation type, check for escapes.
if trivia.last_quote_char == good_single(&quotes_settings.inline_quotes) { if trivia.last_quote_char == good_single(quotes_settings.inline_quotes) {
if !quotes_settings.avoid_escape if !quotes_settings.avoid_escape
|| trivia.prefix.contains('r') || trivia.prefix.contains('r')
|| trivia.prefix.contains('R') || trivia.prefix.contains('R')
@ -381,13 +381,13 @@ fn strings(
continue; continue;
} }
if string_contents.contains(good_single(&quotes_settings.inline_quotes)) if string_contents.contains(good_single(quotes_settings.inline_quotes))
&& !string_contents.contains(bad_single(&quotes_settings.inline_quotes)) && !string_contents.contains(bad_single(quotes_settings.inline_quotes))
{ {
let mut diagnostic = let mut diagnostic =
Diagnostic::new(AvoidableEscapedQuote, Range::new(*start, *end)); Diagnostic::new(AvoidableEscapedQuote, Range::new(*start, *end));
if autofix.into() && settings.rules.should_fix(Rule::AvoidableEscapedQuote) { if autofix.into() && settings.rules.should_fix(Rule::AvoidableEscapedQuote) {
let quote = bad_single(&quotes_settings.inline_quotes); let quote = bad_single(quotes_settings.inline_quotes);
let mut fixed_contents = let mut fixed_contents =
String::with_capacity(trivia.prefix.len() + string_contents.len() + 2); String::with_capacity(trivia.prefix.len() + string_contents.len() + 2);
@ -441,12 +441,12 @@ fn strings(
if !relax_quote { if !relax_quote {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
BadQuotesInlineString { BadQuotesInlineString {
quote: quotes_settings.inline_quotes.clone(), quote: quotes_settings.inline_quotes,
}, },
Range::new(*start, *end), Range::new(*start, *end),
); );
if autofix.into() && settings.rules.should_fix(Rule::BadQuotesInlineString) { if autofix.into() && settings.rules.should_fix(Rule::BadQuotesInlineString) {
let quote = good_single(&quotes_settings.inline_quotes); let quote = good_single(quotes_settings.inline_quotes);
let mut fixed_contents = let mut fixed_contents =
String::with_capacity(trivia.prefix.len() + string_contents.len() + 2); String::with_capacity(trivia.prefix.len() + string_contents.len() + 2);
fixed_contents.push_str(trivia.prefix); fixed_contents.push_str(trivia.prefix);

View file

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions}; use ruff_macros::{CacheKey, ConfigurationOptions};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey, JsonSchema)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey, JsonSchema)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")] #[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub enum Quote { pub enum Quote {
/// Use single quotes. /// Use single quotes.

View file

@ -1,6 +1,6 @@
use std::fmt; use std::fmt;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Branch { pub enum Branch {
Elif, Elif,
Else, Else,

View file

@ -114,7 +114,7 @@ pub(crate) fn fix_nested_if_statements(
outer_if.body = inner_if.body.clone(); outer_if.body = inner_if.body.clone();
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..Default::default() ..Default::default()
}; };

View file

@ -78,7 +78,7 @@ pub(crate) fn fix_multiple_with_statements(
outer_with.body = inner_with.body.clone(); outer_with.body = inner_with.body.clone();
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -43,7 +43,7 @@ fn get_value_content_for_key_in_dict(
let attribute = match_attribute(&mut call.func)?; let attribute = match_attribute(&mut call.func)?;
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -123,7 +123,7 @@ fn reverse_comparison(expr: &Expr, locator: &Locator, stylist: &Stylist) -> Resu
}; };
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -14,7 +14,9 @@ use crate::registry::AsRule;
pub type Settings = Strictness; pub type Settings = Strictness;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey, JsonSchema, Default)] #[derive(
Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey, JsonSchema, Default,
)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")] #[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub enum Strictness { pub enum Strictness {
/// Ban imports that extend into the parent module or beyond. /// Ban imports that extend into the parent module or beyond.
@ -166,7 +168,7 @@ pub fn banned_relative_import(
if level? > &strictness_level { if level? > &strictness_level {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
RelativeImports { RelativeImports {
strictness: strictness.clone(), strictness: *strictness,
}, },
Range::from(stmt), Range::from(stmt),
); );

View file

@ -82,7 +82,7 @@ impl Violation for UnusedLambdaArgument {
/// Check a plain function for unused arguments. /// Check a plain function for unused arguments.
fn function( fn function(
argumentable: &Argumentable, argumentable: Argumentable,
args: &Arguments, args: &Arguments,
values: &Scope, values: &Scope,
bindings: &Bindings, bindings: &Bindings,
@ -109,7 +109,7 @@ fn function(
/// Check a method for unused arguments. /// Check a method for unused arguments.
fn method( fn method(
argumentable: &Argumentable, argumentable: Argumentable,
args: &Arguments, args: &Arguments,
values: &Scope, values: &Scope,
bindings: &Bindings, bindings: &Bindings,
@ -136,7 +136,7 @@ fn method(
} }
fn call<'a>( fn call<'a>(
argumentable: &Argumentable, argumentable: Argumentable,
args: impl Iterator<Item = &'a Arg>, args: impl Iterator<Item = &'a Arg>,
values: &Scope, values: &Scope,
bindings: &Bindings, bindings: &Bindings,
@ -193,7 +193,7 @@ pub fn unused_arguments(
&& !visibility::is_overload(&checker.ctx, decorator_list) && !visibility::is_overload(&checker.ctx, decorator_list)
{ {
function( function(
&Argumentable::Function, Argumentable::Function,
args, args,
scope, scope,
bindings, bindings,
@ -222,7 +222,7 @@ pub fn unused_arguments(
&& !visibility::is_overload(&checker.ctx, decorator_list) && !visibility::is_overload(&checker.ctx, decorator_list)
{ {
method( method(
&Argumentable::Method, Argumentable::Method,
args, args,
scope, scope,
bindings, bindings,
@ -251,7 +251,7 @@ pub fn unused_arguments(
&& !visibility::is_overload(&checker.ctx, decorator_list) && !visibility::is_overload(&checker.ctx, decorator_list)
{ {
method( method(
&Argumentable::ClassMethod, Argumentable::ClassMethod,
args, args,
scope, scope,
bindings, bindings,
@ -280,7 +280,7 @@ pub fn unused_arguments(
&& !visibility::is_overload(&checker.ctx, decorator_list) && !visibility::is_overload(&checker.ctx, decorator_list)
{ {
function( function(
&Argumentable::StaticMethod, Argumentable::StaticMethod,
args, args,
scope, scope,
bindings, bindings,
@ -303,7 +303,7 @@ pub fn unused_arguments(
.enabled(Argumentable::Lambda.rule_code()) .enabled(Argumentable::Lambda.rule_code())
{ {
function( function(
&Argumentable::Lambda, Argumentable::Lambda,
args, args,
scope, scope,
bindings, bindings,

View file

@ -5,6 +5,7 @@ use crate::registry::Rule;
use super::rules; use super::rules;
/// An AST node that can contain arguments. /// An AST node that can contain arguments.
#[derive(Copy, Clone)]
pub enum Argumentable { pub enum Argumentable {
Function, Function,
Method, Method,
@ -14,7 +15,7 @@ pub enum Argumentable {
} }
impl Argumentable { impl Argumentable {
pub fn check_for(&self, name: String) -> DiagnosticKind { pub fn check_for(self, name: String) -> DiagnosticKind {
match self { match self {
Self::Function => rules::UnusedFunctionArgument { name }.into(), Self::Function => rules::UnusedFunctionArgument { name }.into(),
Self::Method => rules::UnusedMethodArgument { name }.into(), Self::Method => rules::UnusedMethodArgument { name }.into(),
@ -24,7 +25,7 @@ impl Argumentable {
} }
} }
pub const fn rule_code(&self) -> Rule { pub const fn rule_code(self) -> Rule {
match self { match self {
Self::Function => Rule::UnusedFunctionArgument, Self::Function => Rule::UnusedFunctionArgument,
Self::Method => Rule::UnusedMethodArgument, Self::Method => Rule::UnusedMethodArgument,

View file

@ -20,6 +20,7 @@ use super::types::{ImportBlock, Importable};
Ord, Ord,
PartialEq, PartialEq,
Eq, Eq,
Copy,
Clone, Clone,
Serialize, Serialize,
Deserialize, Deserialize,

View file

@ -15,11 +15,11 @@ pub fn format_import(
) -> String { ) -> String {
let mut output = String::with_capacity(CAPACITY); let mut output = String::with_capacity(CAPACITY);
if !is_first && !comments.atop.is_empty() { if !is_first && !comments.atop.is_empty() {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
for comment in &comments.atop { for comment in &comments.atop {
output.push_str(comment); output.push_str(comment);
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
if let Some(asname) = alias.asname { if let Some(asname) = alias.asname {
output.push_str("import "); output.push_str("import ");
@ -34,7 +34,7 @@ pub fn format_import(
output.push_str(" "); output.push_str(" ");
output.push_str(comment); output.push_str(comment);
} }
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
output output
} }
@ -94,11 +94,11 @@ fn format_single_line(
let mut line_width = 0; let mut line_width = 0;
if !is_first && !comments.atop.is_empty() { if !is_first && !comments.atop.is_empty() {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
for comment in &comments.atop { for comment in &comments.atop {
output.push_str(comment); output.push_str(comment);
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
let module_name = import_from.module_name(); let module_name = import_from.module_name();
@ -137,7 +137,7 @@ fn format_single_line(
line_width += 2 + comment.width(); line_width += 2 + comment.width();
} }
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
(output, line_width) (output, line_width)
} }
@ -153,11 +153,11 @@ fn format_multi_line(
let mut output = String::with_capacity(CAPACITY); let mut output = String::with_capacity(CAPACITY);
if !is_first && !comments.atop.is_empty() { if !is_first && !comments.atop.is_empty() {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
for comment in &comments.atop { for comment in &comments.atop {
output.push_str(comment); output.push_str(comment);
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
output.push_str("from "); output.push_str("from ");
@ -169,13 +169,13 @@ fn format_multi_line(
output.push(' '); output.push(' ');
output.push_str(comment); output.push_str(comment);
} }
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
for (AliasData { name, asname }, comments) in aliases { for (AliasData { name, asname }, comments) in aliases {
for comment in &comments.atop { for comment in &comments.atop {
output.push_str(stylist.indentation()); output.push_str(stylist.indentation());
output.push_str(comment); output.push_str(comment);
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
output.push_str(stylist.indentation()); output.push_str(stylist.indentation());
if let Some(asname) = asname { if let Some(asname) = asname {
@ -192,11 +192,11 @@ fn format_multi_line(
output.push(' '); output.push(' ');
output.push_str(comment); output.push_str(comment);
} }
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
output.push(')'); output.push(')');
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
output output
} }

View file

@ -172,7 +172,7 @@ pub fn format_imports(
if !block_output.is_empty() && !output.is_empty() { if !block_output.is_empty() && !output.is_empty() {
// If we are about to output something, and had already // If we are about to output something, and had already
// output a block, separate them. // output a block, separate them.
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
output.push_str(block_output.as_str()); output.push_str(block_output.as_str());
} }
@ -182,20 +182,20 @@ pub fn format_imports(
Some(Trailer::Sibling) => { Some(Trailer::Sibling) => {
if lines_after_imports >= 0 { if lines_after_imports >= 0 {
for _ in 0..lines_after_imports { for _ in 0..lines_after_imports {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
} else { } else {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
} }
Some(Trailer::FunctionDef | Trailer::ClassDef) => { Some(Trailer::FunctionDef | Trailer::ClassDef) => {
if lines_after_imports >= 0 { if lines_after_imports >= 0 {
for _ in 0..lines_after_imports { for _ in 0..lines_after_imports {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
} else { } else {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
} }
} }
@ -277,7 +277,7 @@ fn format_import_block(
is_first_block = false; is_first_block = false;
pending_lines_before = false; pending_lines_before = false;
} else if pending_lines_before { } else if pending_lines_before {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
pending_lines_before = false; pending_lines_before = false;
} }
@ -301,7 +301,7 @@ fn format_import_block(
// Add a blank lines between direct and from imports // Add a blank lines between direct and from imports
if lines_between_types > 0 && has_direct_import && !lines_inserted { if lines_between_types > 0 && has_direct_import && !lines_inserted {
for _ in 0..lines_between_types { for _ in 0..lines_between_types {
output.push_str(stylist.line_ending()); output.push_str(&stylist.line_ending());
} }
lines_inserted = true; lines_inserted = true;

View file

@ -10,7 +10,7 @@ use super::settings::RelativeImportsOrder;
use super::types::EitherImport::{Import, ImportFrom}; use super::types::EitherImport::{Import, ImportFrom};
use super::types::{AliasData, EitherImport, ImportFromData}; use super::types::{AliasData, EitherImport, ImportFromData};
#[derive(PartialOrd, Ord, PartialEq, Eq)] #[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
pub enum Prefix { pub enum Prefix {
Constants, Constants,
Classes, Classes,

View file

@ -14,7 +14,7 @@ use crate::directives::IsortDirectives;
use super::helpers; use super::helpers;
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
pub enum Trailer { pub enum Trailer {
Sibling, Sibling,
ClassDef, ClassDef,

View file

@ -11,7 +11,7 @@ use crate::checkers::ast::Checker;
use crate::registry::AsRule; use crate::registry::AsRule;
use crate::rules::pycodestyle::helpers::compare; use crate::rules::pycodestyle::helpers::compare;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum EqCmpop { pub enum EqCmpop {
Eq, Eq,
NotEq, NotEq,

View file

@ -93,11 +93,7 @@ impl Violation for UndocumentedPublicInit {
} }
/// D100, D101, D102, D103, D104, D105, D106, D107 /// D100, D101, D102, D103, D104, D105, D106, D107
pub fn not_missing( pub fn not_missing(checker: &mut Checker, definition: &Definition, visibility: Visibility) -> bool {
checker: &mut Checker,
definition: &Definition,
visibility: &Visibility,
) -> bool {
if matches!(visibility, Visibility::Private) { if matches!(visibility, Visibility::Private) {
return true; return true;
} }

View file

@ -280,12 +280,12 @@ pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option
match convention { match convention {
Some(Convention::Google) => { Some(Convention::Google) => {
for context in &section_contexts(&lines, &SectionStyle::Google) { for context in &section_contexts(&lines, SectionStyle::Google) {
google_section(checker, docstring, context); google_section(checker, docstring, context);
} }
} }
Some(Convention::Numpy) => { Some(Convention::Numpy) => {
for context in &section_contexts(&lines, &SectionStyle::Numpy) { for context in &section_contexts(&lines, SectionStyle::Numpy) {
numpy_section(checker, docstring, context); numpy_section(checker, docstring, context);
} }
} }
@ -296,7 +296,7 @@ pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option
// If the docstring contains `Parameters:` or `Other Parameters:`, use the NumPy // If the docstring contains `Parameters:` or `Other Parameters:`, use the NumPy
// convention. // convention.
let numpy_sections = section_contexts(&lines, &SectionStyle::Numpy); let numpy_sections = section_contexts(&lines, SectionStyle::Numpy);
if numpy_sections.iter().any(|context| { if numpy_sections.iter().any(|context| {
matches!( matches!(
context.kind, context.kind,
@ -310,7 +310,7 @@ pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option
} }
// If the docstring contains `Args:` or `Arguments:`, use the Google convention. // If the docstring contains `Args:` or `Arguments:`, use the Google convention.
let google_sections = section_contexts(&lines, &SectionStyle::Google); let google_sections = section_contexts(&lines, SectionStyle::Google);
if google_sections if google_sections
.iter() .iter()
.any(|context| matches!(context.kind, SectionKind::Arguments | SectionKind::Args)) .any(|context| matches!(context.kind, SectionKind::Arguments | SectionKind::Args))

View file

@ -34,7 +34,7 @@ pub fn remove_unused_format_arguments_from_dict(
}); });
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -62,7 +62,7 @@ pub fn remove_unused_keyword_arguments_from_format_call(
.retain(|e| !matches!(&e.keyword, Some(kw) if unused_arguments.contains(&kw.value))); .retain(|e| !matches!(&e.keyword, Some(kw) if unused_arguments.contains(&kw.value)));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -170,7 +170,7 @@ pub fn remove_unused_positional_arguments_from_format_call(
} }
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -9,7 +9,7 @@ use ruff_python_stdlib::future::ALL_FEATURE_NAMES;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum UnusedImportContext { pub enum UnusedImportContext {
ExceptHandler, ExceptHandler,
Init, Init,

View file

@ -12,7 +12,7 @@ use ruff_python_ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::registry::AsRule; use crate::registry::AsRule;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum IsCmpop { pub enum IsCmpop {
Is, Is,
IsNot, IsNot,

View file

@ -183,6 +183,7 @@ where
unreachable!("No token after matched"); unreachable!("No token after matched");
} }
#[derive(Copy, Clone)]
enum DeletionKind { enum DeletionKind {
Whole, Whole,
Partial, Partial,

View file

@ -30,7 +30,7 @@ impl Violation for BadStrStripCall {
} }
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum StripKind { pub enum StripKind {
Strip, Strip,
LStrip, LStrip,
@ -59,14 +59,14 @@ impl fmt::Display for StripKind {
} }
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum RemovalKind { pub enum RemovalKind {
RemovePrefix, RemovePrefix,
RemoveSuffix, RemoveSuffix,
} }
impl RemovalKind { impl RemovalKind {
pub fn for_strip(s: &StripKind) -> Option<Self> { pub fn for_strip(s: StripKind) -> Option<Self> {
match s { match s {
StripKind::Strip => None, StripKind::Strip => None,
StripKind::LStrip => Some(Self::RemovePrefix), StripKind::LStrip => Some(Self::RemovePrefix),
@ -126,7 +126,7 @@ pub fn bad_str_strip_call(checker: &mut Checker, func: &Expr, args: &[Expr]) {
if has_duplicates(value) { if has_duplicates(value) {
let removal = if checker.settings.target_version >= PythonVersion::Py39 let removal = if checker.settings.target_version >= PythonVersion::Py39
{ {
RemovalKind::for_strip(&strip) RemovalKind::for_strip(strip)
} else { } else {
None None
}; };

View file

@ -38,7 +38,7 @@ impl Violation for BadStringFormatType {
} }
} }
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
enum DataType { enum DataType {
String, String,
Integer, Integer,
@ -87,7 +87,7 @@ impl From<&Expr> for DataType {
} }
impl DataType { impl DataType {
fn is_compatible_with(&self, format: &FormatType) -> bool { fn is_compatible_with(self, format: FormatType) -> bool {
match self { match self {
DataType::String => matches!( DataType::String => matches!(
format, format,
@ -119,7 +119,7 @@ impl DataType {
} }
} }
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
enum FormatType { enum FormatType {
Repr, Repr,
String, String,
@ -161,7 +161,7 @@ fn collect_specs(formats: &[CFormatStrOrBytes<String>]) -> Vec<&CFormatSpec> {
fn equivalent(format: &CFormatSpec, value: &Expr) -> bool { fn equivalent(format: &CFormatSpec, value: &Expr) -> bool {
let constant: DataType = value.into(); let constant: DataType = value.into();
let format: FormatType = format.format_char.into(); let format: FormatType = format.format_char.into();
constant.is_compatible_with(&format) constant.is_compatible_with(format)
} }
/// Return `true` if the [`Constnat`] aligns with the format type. /// Return `true` if the [`Constnat`] aligns with the format type.

View file

@ -10,7 +10,7 @@ use ruff_python_ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum ViolationsCmpop { pub enum ViolationsCmpop {
Eq, Eq,
NotEq, NotEq,

View file

@ -35,7 +35,7 @@ pub fn adjust_indentation(
indented_block.indent = Some(indentation); indented_block.indent = Some(indentation);
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..Default::default() ..Default::default()
}; };
@ -71,7 +71,7 @@ pub fn remove_super_arguments(locator: &Locator, stylist: &Stylist, expr: &Expr)
body.whitespace_after_func = ParenthesizableWhitespace::default(); body.whitespace_after_func = ParenthesizableWhitespace::default();
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -17,7 +17,7 @@ use crate::checkers::ast::Checker;
use crate::cst::matchers::{match_import, match_import_from, match_module}; use crate::cst::matchers::{match_import, match_import_from, match_module};
use crate::registry::{AsRule, Rule}; use crate::registry::{AsRule, Rule};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum MockReference { pub enum MockReference {
Import, Import,
Attribute, Attribute,
@ -99,7 +99,7 @@ fn format_mocks(aliases: Vec<Option<AsName>>, indent: &str, stylist: &Stylist) -
match alias { match alias {
None => { None => {
if !content.is_empty() { if !content.is_empty() {
content.push_str(stylist.line_ending()); content.push_str(&stylist.line_ending());
content.push_str(indent); content.push_str(indent);
} }
content.push_str("from unittest import mock"); content.push_str("from unittest import mock");
@ -107,7 +107,7 @@ fn format_mocks(aliases: Vec<Option<AsName>>, indent: &str, stylist: &Stylist) -
Some(as_name) => { Some(as_name) => {
if let AssignTargetExpression::Name(name) = as_name.name { if let AssignTargetExpression::Name(name) = as_name.name {
if !content.is_empty() { if !content.is_empty() {
content.push_str(stylist.line_ending()); content.push_str(&stylist.line_ending());
content.push_str(indent); content.push_str(indent);
} }
content.push_str("from unittest import mock as "); content.push_str("from unittest import mock as ");
@ -139,14 +139,14 @@ fn format_import(
import.names = clean_aliases; import.names = clean_aliases;
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
tree.codegen(&mut state); tree.codegen(&mut state);
let mut content = state.to_string(); let mut content = state.to_string();
content.push_str(stylist.line_ending()); content.push_str(&stylist.line_ending());
content.push_str(indent); content.push_str(indent);
content.push_str(&format_mocks(mock_aliases, indent, stylist)); content.push_str(&format_mocks(mock_aliases, indent, stylist));
content content
@ -189,7 +189,7 @@ fn format_import_from(
rpar: vec![], rpar: vec![],
}))); })));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -226,7 +226,7 @@ fn format_import_from(
}))); })));
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -234,7 +234,7 @@ fn format_import_from(
let mut content = state.to_string(); let mut content = state.to_string();
if !mock_aliases.is_empty() { if !mock_aliases.is_empty() {
content.push_str(stylist.line_ending()); content.push_str(&stylist.line_ending());
content.push_str(indent); content.push_str(indent);
content.push_str(&format_mocks(mock_aliases, indent, stylist)); content.push_str(&format_mocks(mock_aliases, indent, stylist));
} }

View file

@ -101,7 +101,7 @@ fn generate_call(
}; };
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };
@ -111,7 +111,7 @@ fn generate_call(
call.func = Box::new(match_expression(&cleaned)?); call.func = Box::new(match_expression(&cleaned)?);
let mut state = CodegenState { let mut state = CodegenState {
default_newline: stylist.line_ending(), default_newline: &stylist.line_ending(),
default_indent: stylist.indentation(), default_indent: stylist.indentation(),
..CodegenState::default() ..CodegenState::default()
}; };

View file

@ -10,7 +10,7 @@ use ruff_python_ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::registry::AsRule; use crate::registry::AsRule;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum LiteralType { pub enum LiteralType {
Str, Str,
Bytes, Bytes,

View file

@ -44,6 +44,7 @@ impl AlwaysAutofixableViolation for RedundantOpenModes {
const OPEN_FUNC_NAME: &str = "open"; const OPEN_FUNC_NAME: &str = "open";
const MODE_KEYWORD_ARGUMENT: &str = "mode"; const MODE_KEYWORD_ARGUMENT: &str = "mode";
#[derive(Copy, Clone)]
enum OpenMode { enum OpenMode {
U, U,
Ur, Ur,
@ -72,15 +73,15 @@ impl FromStr for OpenMode {
} }
impl OpenMode { impl OpenMode {
fn replacement_value(&self) -> Option<String> { fn replacement_value(self) -> Option<&'static str> {
match *self { match self {
Self::U => None, Self::U => None,
Self::Ur => None, Self::Ur => None,
Self::Ub => Some(String::from("\"rb\"")), Self::Ub => Some("\"rb\""),
Self::RUb => Some(String::from("\"rb\"")), Self::RUb => Some("\"rb\""),
Self::R => None, Self::R => None,
Self::Rt => None, Self::Rt => None,
Self::Wt => Some(String::from("\"w\"")), Self::Wt => Some("\"w\""),
} }
} }
} }
@ -103,20 +104,20 @@ fn match_open(expr: &Expr) -> (Option<&Expr>, Vec<Keyword>) {
fn create_check( fn create_check(
expr: &Expr, expr: &Expr,
mode_param: &Expr, mode_param: &Expr,
replacement_value: Option<String>, replacement_value: Option<&str>,
locator: &Locator, locator: &Locator,
patch: bool, patch: bool,
) -> Diagnostic { ) -> Diagnostic {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
RedundantOpenModes { RedundantOpenModes {
replacement: replacement_value.clone(), replacement: replacement_value.map(ToString::to_string),
}, },
Range::from(expr), Range::from(expr),
); );
if patch { if patch {
if let Some(content) = replacement_value { if let Some(content) = replacement_value {
diagnostic.set_fix(Edit::replacement( diagnostic.set_fix(Edit::replacement(
content, content.to_string(),
mode_param.location, mode_param.location,
mode_param.end_location.unwrap(), mode_param.end_location.unwrap(),
)); ));

View file

@ -123,7 +123,7 @@ pub fn unnecessary_builtin_import(
) { ) {
Ok(fix) => { Ok(fix) => {
if fix.content.is_empty() || fix.content == "pass" { if fix.content.is_empty() || fix.content == "pass" {
checker.deletions.insert(defined_by.clone()); checker.deletions.insert(*defined_by);
} }
diagnostic.set_fix(fix); diagnostic.set_fix(fix);
} }

View file

@ -103,7 +103,7 @@ pub fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, names: &[Lo
) { ) {
Ok(fix) => { Ok(fix) => {
if fix.content.is_empty() || fix.content == "pass" { if fix.content.is_empty() || fix.content == "pass" {
checker.deletions.insert(defined_by.clone()); checker.deletions.insert(*defined_by);
} }
diagnostic.set_fix(fix); diagnostic.set_fix(fix);
} }

View file

@ -74,6 +74,7 @@ fn any_arg_is_str(slice: &Expr) -> bool {
} }
} }
#[derive(Copy, Clone)]
enum TypingMember { enum TypingMember {
Union, Union,
Optional, Optional,

View file

@ -10,7 +10,7 @@ use ruff_python_ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::registry::AsRule; use crate::registry::AsRule;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum CallKind { pub enum CallKind {
Isinstance, Isinstance,
Issubclass, Issubclass,

View file

@ -62,7 +62,7 @@ pub fn useless_metaclass_type(checker: &mut Checker, stmt: &Stmt, value: &Expr,
) { ) {
Ok(fix) => { Ok(fix) => {
if fix.content.is_empty() || fix.content == "pass" { if fix.content.is_empty() || fix.content == "pass" {
checker.deletions.insert(defined_by.clone()); checker.deletions.insert(*defined_by);
} }
diagnostic.set_fix(fix); diagnostic.set_fix(fix);
} }

View file

@ -62,7 +62,7 @@ impl Violation for AsyncioDanglingTask {
} }
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Method { pub enum Method {
CreateTask, CreateTask,
EnsureFuture, EnsureFuture,

View file

@ -49,7 +49,7 @@ fn make_splat_elts(
new_elts new_elts
} }
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
enum Kind { enum Kind {
List, List,
Tuple, Tuple,

View file

@ -23,6 +23,7 @@ mod panic;
mod printer; mod printer;
mod resolve; mod resolve;
#[derive(Copy, Clone)]
pub enum ExitStatus { pub enum ExitStatus {
/// Linting was successful and there were no linting errors. /// Linting was successful and there were no linting errors.
Success, Success,

View file

@ -1,5 +1,6 @@
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
#[derive(Copy, Clone)]
pub enum AutofixKind { pub enum AutofixKind {
Sometimes, Sometimes,
Always, Always,

View file

@ -8,40 +8,39 @@ use crate::types::RefEquality;
/// Return the common ancestor of `left` and `right` below `stop`, or `None`. /// Return the common ancestor of `left` and `right` below `stop`, or `None`.
fn common_ancestor<'a>( fn common_ancestor<'a>(
left: &'a RefEquality<'a, Stmt>, left: RefEquality<'a, Stmt>,
right: &'a RefEquality<'a, Stmt>, right: RefEquality<'a, Stmt>,
stop: Option<&'a RefEquality<'a, Stmt>>, stop: Option<RefEquality<'a, Stmt>>,
depths: &'a FxHashMap<RefEquality<'a, Stmt>, usize>, depths: &'a FxHashMap<RefEquality<'a, Stmt>, usize>,
child_to_parent: &'a FxHashMap<RefEquality<'a, Stmt>, RefEquality<'a, Stmt>>, child_to_parent: &'a FxHashMap<RefEquality<'a, Stmt>, RefEquality<'a, Stmt>>,
) -> Option<&'a RefEquality<'a, Stmt>> { ) -> Option<RefEquality<'a, Stmt>> {
if let Some(stop) = stop { if Some(left) == stop || Some(right) == stop {
if left == stop || right == stop { return None;
return None;
}
} }
if left == right { if left == right {
return Some(left); return Some(left);
} }
let left_depth = depths.get(left)?; let left_depth = depths.get(&left)?;
let right_depth = depths.get(right)?; let right_depth = depths.get(&right)?;
match left_depth.cmp(right_depth) { match left_depth.cmp(right_depth) {
Ordering::Less => common_ancestor( Ordering::Less => common_ancestor(
left, left,
child_to_parent.get(right)?, *child_to_parent.get(&right)?,
stop, stop,
depths, depths,
child_to_parent, child_to_parent,
), ),
Ordering::Equal => common_ancestor( Ordering::Equal => common_ancestor(
child_to_parent.get(left)?, *child_to_parent.get(&left)?,
child_to_parent.get(right)?, *child_to_parent.get(&right)?,
stop, stop,
depths, depths,
child_to_parent, child_to_parent,
), ),
Ordering::Greater => common_ancestor( Ordering::Greater => common_ancestor(
child_to_parent.get(left)?, *child_to_parent.get(&left)?,
right, right,
stop, stop,
depths, depths,
@ -51,8 +50,8 @@ fn common_ancestor<'a>(
} }
/// Return the alternative branches for a given node. /// Return the alternative branches for a given node.
fn alternatives<'a>(stmt: &'a RefEquality<'a, Stmt>) -> Vec<Vec<RefEquality<'a, Stmt>>> { fn alternatives(stmt: RefEquality<Stmt>) -> Vec<Vec<RefEquality<Stmt>>> {
match &stmt.node { match &stmt.as_ref().node {
StmtKind::If { body, .. } => vec![body.iter().map(RefEquality).collect()], StmtKind::If { body, .. } => vec![body.iter().map(RefEquality).collect()],
StmtKind::Try { StmtKind::Try {
body, body,
@ -78,22 +77,22 @@ fn alternatives<'a>(stmt: &'a RefEquality<'a, Stmt>) -> Vec<Vec<RefEquality<'a,
/// Return `true` if `stmt` is a descendent of any of the nodes in `ancestors`. /// Return `true` if `stmt` is a descendent of any of the nodes in `ancestors`.
fn descendant_of<'a>( fn descendant_of<'a>(
stmt: &RefEquality<'a, Stmt>, stmt: RefEquality<'a, Stmt>,
ancestors: &[RefEquality<'a, Stmt>], ancestors: &[RefEquality<'a, Stmt>],
stop: &RefEquality<'a, Stmt>, stop: RefEquality<'a, Stmt>,
depths: &FxHashMap<RefEquality<'a, Stmt>, usize>, depths: &FxHashMap<RefEquality<'a, Stmt>, usize>,
child_to_parent: &FxHashMap<RefEquality<'a, Stmt>, RefEquality<'a, Stmt>>, child_to_parent: &FxHashMap<RefEquality<'a, Stmt>, RefEquality<'a, Stmt>>,
) -> bool { ) -> bool {
ancestors.iter().any(|ancestor| { ancestors.iter().any(|ancestor| {
common_ancestor(stmt, ancestor, Some(stop), depths, child_to_parent).is_some() common_ancestor(stmt, *ancestor, Some(stop), depths, child_to_parent).is_some()
}) })
} }
/// Return `true` if `left` and `right` are on different branches of an `if` or /// Return `true` if `left` and `right` are on different branches of an `if` or
/// `try` statement. /// `try` statement.
pub fn different_forks<'a>( pub fn different_forks<'a>(
left: &RefEquality<'a, Stmt>, left: RefEquality<'a, Stmt>,
right: &RefEquality<'a, Stmt>, right: RefEquality<'a, Stmt>,
depths: &FxHashMap<RefEquality<'a, Stmt>, usize>, depths: &FxHashMap<RefEquality<'a, Stmt>, usize>,
child_to_parent: &FxHashMap<RefEquality<'a, Stmt>, RefEquality<'a, Stmt>>, child_to_parent: &FxHashMap<RefEquality<'a, Stmt>, RefEquality<'a, Stmt>>,
) -> bool { ) -> bool {

View file

@ -9,7 +9,7 @@ use rustpython_parser::ast::{
use num_bigint::BigInt; use num_bigint::BigInt;
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableExprContext { pub enum ComparableExprContext {
Load, Load,
Store, Store,
@ -26,7 +26,7 @@ impl From<&ExprContext> for ComparableExprContext {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableBoolop { pub enum ComparableBoolop {
And, And,
Or, Or,
@ -41,7 +41,7 @@ impl From<&Boolop> for ComparableBoolop {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableOperator { pub enum ComparableOperator {
Add, Add,
Sub, Sub,
@ -78,7 +78,7 @@ impl From<&Operator> for ComparableOperator {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableUnaryop { pub enum ComparableUnaryop {
Invert, Invert,
Not, Not,
@ -97,7 +97,7 @@ impl From<&Unaryop> for ComparableUnaryop {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableCmpop { pub enum ComparableCmpop {
Eq, Eq,
NotEq, NotEq,

View file

@ -206,13 +206,10 @@ impl<'a> Context<'a> {
pub fn push_parent(&mut self, parent: &'a Stmt) { pub fn push_parent(&mut self, parent: &'a Stmt) {
let num_existing = self.parents.len(); let num_existing = self.parents.len();
self.parents.push(RefEquality(parent)); self.parents.push(RefEquality(parent));
self.depths self.depths.insert(self.parents[num_existing], num_existing);
.insert(self.parents[num_existing].clone(), num_existing);
if num_existing > 0 { if num_existing > 0 {
self.child_to_parent.insert( self.child_to_parent
self.parents[num_existing].clone(), .insert(self.parents[num_existing], self.parents[num_existing - 1]);
self.parents[num_existing - 1].clone(),
);
} }
} }

View file

@ -7,6 +7,7 @@ use crate::scope::{Scope, ScopeKind};
const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"]; const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"];
const METACLASS_BASES: [(&str, &str); 2] = [("", "type"), ("abc", "ABCMeta")]; const METACLASS_BASES: [(&str, &str); 2] = [("", "type"), ("abc", "ABCMeta")];
#[derive(Copy, Clone)]
pub enum FunctionType { pub enum FunctionType {
Function, Function,
Method, Method,

View file

@ -1,3 +1,4 @@
#[derive(Copy, Clone)]
pub enum LoggingLevel { pub enum LoggingLevel {
Debug, Debug,
Critical, Critical,

View file

@ -215,8 +215,19 @@ impl ScopeStack {
pub fn iter(&self) -> std::iter::Rev<std::slice::Iter<ScopeId>> { pub fn iter(&self) -> std::iter::Rev<std::slice::Iter<ScopeId>> {
self.0.iter().rev() self.0.iter().rev()
} }
pub fn snapshot(&self) -> ScopeStackSnapshot {
ScopeStackSnapshot(self.0.len())
}
#[allow(clippy::needless_pass_by_value)]
pub fn restore(&mut self, snapshot: ScopeStackSnapshot) {
self.0.truncate(snapshot.0);
}
} }
pub struct ScopeStackSnapshot(usize);
impl Default for ScopeStack { impl Default for ScopeStack {
fn default() -> Self { fn default() -> Self {
Self(vec![ScopeId::global()]) Self(vec![ScopeId::global()])

View file

@ -65,7 +65,7 @@ pub struct Generator<'a> {
/// The quote style to use for string literals. /// The quote style to use for string literals.
quote: Quote, quote: Quote,
/// The line ending to use. /// The line ending to use.
line_ending: &'a LineEnding, line_ending: LineEnding,
buffer: String, buffer: String,
indent_depth: usize, indent_depth: usize,
num_newlines: usize, num_newlines: usize,
@ -87,7 +87,7 @@ impl<'a> From<&'a Stylist<'a>> for Generator<'a> {
} }
impl<'a> Generator<'a> { impl<'a> Generator<'a> {
pub const fn new(indent: &'a Indentation, quote: Quote, line_ending: &'a LineEnding) -> Self { pub const fn new(indent: &'a Indentation, quote: Quote, line_ending: LineEnding) -> Self {
Self { Self {
// Style preferences. // Style preferences.
indent, indent,
@ -128,7 +128,7 @@ impl<'a> Generator<'a> {
fn p(&mut self, s: &str) { fn p(&mut self, s: &str) {
if self.num_newlines > 0 { if self.num_newlines > 0 {
for _ in 0..self.num_newlines { for _ in 0..self.num_newlines {
self.buffer += self.line_ending; self.buffer += &self.line_ending;
} }
self.num_newlines = 0; self.num_newlines = 0;
} }
@ -1266,7 +1266,7 @@ mod tests {
let line_ending = LineEnding::default(); let line_ending = LineEnding::default();
let program = parser::parse_program(contents, "<filename>").unwrap(); let program = parser::parse_program(contents, "<filename>").unwrap();
let stmt = program.first().unwrap(); let stmt = program.first().unwrap();
let mut generator = Generator::new(&indentation, quote, &line_ending); let mut generator = Generator::new(&indentation, quote, line_ending);
generator.unparse_stmt(stmt); generator.unparse_stmt(stmt);
generator.generate() generator.generate()
} }
@ -1274,7 +1274,7 @@ mod tests {
fn round_trip_with( fn round_trip_with(
indentation: &Indentation, indentation: &Indentation,
quote: Quote, quote: Quote,
line_ending: &LineEnding, line_ending: LineEnding,
contents: &str, contents: &str,
) -> String { ) -> String {
let program = parser::parse_program(contents, "<filename>").unwrap(); let program = parser::parse_program(contents, "<filename>").unwrap();
@ -1449,7 +1449,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::Double, Quote::Double,
&LineEnding::default(), LineEnding::default(),
r#""hello""# r#""hello""#
), ),
r#""hello""# r#""hello""#
@ -1458,7 +1458,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::Single, Quote::Single,
&LineEnding::default(), LineEnding::default(),
r#""hello""# r#""hello""#
), ),
r#"'hello'"# r#"'hello'"#
@ -1467,7 +1467,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::Double, Quote::Double,
&LineEnding::default(), LineEnding::default(),
r#"'hello'"# r#"'hello'"#
), ),
r#""hello""# r#""hello""#
@ -1476,7 +1476,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::Single, Quote::Single,
&LineEnding::default(), LineEnding::default(),
r#"'hello'"# r#"'hello'"#
), ),
r#"'hello'"# r#"'hello'"#
@ -1489,7 +1489,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::new(" ".to_string()), &Indentation::new(" ".to_string()),
Quote::default(), Quote::default(),
&LineEnding::default(), LineEnding::default(),
r#" r#"
if True: if True:
pass pass
@ -1507,7 +1507,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::new(" ".to_string()), &Indentation::new(" ".to_string()),
Quote::default(), Quote::default(),
&LineEnding::default(), LineEnding::default(),
r#" r#"
if True: if True:
pass pass
@ -1525,7 +1525,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::new("\t".to_string()), &Indentation::new("\t".to_string()),
Quote::default(), Quote::default(),
&LineEnding::default(), LineEnding::default(),
r#" r#"
if True: if True:
pass pass
@ -1547,7 +1547,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::default(), Quote::default(),
&LineEnding::Lf, LineEnding::Lf,
"if True:\n print(42)", "if True:\n print(42)",
), ),
"if True:\n print(42)", "if True:\n print(42)",
@ -1557,7 +1557,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::default(), Quote::default(),
&LineEnding::CrLf, LineEnding::CrLf,
"if True:\n print(42)", "if True:\n print(42)",
), ),
"if True:\r\n print(42)", "if True:\r\n print(42)",
@ -1567,7 +1567,7 @@ if True:
round_trip_with( round_trip_with(
&Indentation::default(), &Indentation::default(),
Quote::default(), Quote::default(),
&LineEnding::Cr, LineEnding::Cr,
"if True:\n print(42)", "if True:\n print(42)",
), ),
"if True:\r print(42)", "if True:\r print(42)",

View file

@ -56,8 +56,9 @@ impl<'a> Stylist<'a> {
}) })
} }
pub fn line_ending(&'a self) -> &'a LineEnding { pub fn line_ending(&'a self) -> LineEnding {
self.line_ending *self
.line_ending
.get_or_init(|| detect_line_ending(self.locator.contents()).unwrap_or_default()) .get_or_init(|| detect_line_ending(self.locator.contents()).unwrap_or_default())
} }
@ -160,7 +161,7 @@ impl Deref for Indentation {
/// The line ending style used in Python source code. /// The line ending style used in Python source code.
/// See <https://docs.python.org/3/reference/lexical_analysis.html#physical-lines> /// See <https://docs.python.org/3/reference/lexical_analysis.html#physical-lines>
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum LineEnding { pub enum LineEnding {
Lf, Lf,
Cr, Cr,

View file

@ -35,9 +35,32 @@ impl<T> From<&Box<Located<T>>> for Range {
} }
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug)]
pub struct RefEquality<'a, T>(pub &'a T); pub struct RefEquality<'a, T>(pub &'a T);
impl<'a, T> RefEquality<'a, T> {
// More specific implementation that keeps the `'a` lifetime.
// It's otherwise the same as [`AsRef::as_ref`]
#[allow(clippy::should_implement_trait)]
pub fn as_ref(&self) -> &'a T {
self.0
}
}
impl<'a, T> AsRef<T> for RefEquality<'a, T> {
fn as_ref(&self) -> &T {
self.0
}
}
impl<'a, T> Clone for RefEquality<'a, T> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<'a, T> Copy for RefEquality<'a, T> {}
impl<'a, T> std::hash::Hash for RefEquality<'a, T> { impl<'a, T> std::hash::Hash for RefEquality<'a, T> {
fn hash<H>(&self, state: &mut H) fn hash<H>(&self, state: &mut H)
where where

View file

@ -10,6 +10,7 @@ use crate::source_code::Locator;
use crate::str; use crate::str;
use crate::types::Range; use crate::types::Range;
#[derive(Copy, Clone)]
pub enum Callable { pub enum Callable {
Cast, Cast,
NewType, NewType,
@ -19,6 +20,7 @@ pub enum Callable {
MypyExtension, MypyExtension,
} }
#[derive(Copy, Clone)]
pub enum SubscriptKind { pub enum SubscriptKind {
AnnotatedSubscript, AnnotatedSubscript,
PEP593AnnotatedSubscript, PEP593AnnotatedSubscript,
@ -72,7 +74,7 @@ pub fn is_pep585_builtin(expr: &Expr, context: &Context) -> bool {
}) })
} }
#[derive(is_macro::Is)] #[derive(is_macro::Is, Copy, Clone)]
pub enum AnnotationKind { pub enum AnnotationKind {
/// The annotation is defined as part a simple string literal, /// The annotation is defined as part a simple string literal,
/// e.g. `x: "List[int]" = []`. Annotations within simple literals /// e.g. `x: "List[int]" = []`. Annotations within simple literals

View file

@ -6,20 +6,20 @@ use crate::context::Context;
use crate::helpers::{collect_call_path, map_callable}; use crate::helpers::{collect_call_path, map_callable};
use crate::types::CallPath; use crate::types::CallPath;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
pub enum Modifier { pub enum Modifier {
Module, Module,
Class, Class,
Function, Function,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
pub enum Visibility { pub enum Visibility {
Public, Public,
Private, Private,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
pub struct VisibleScope { pub struct VisibleScope {
pub modifier: Modifier, pub modifier: Modifier,
pub visibility: Visibility, pub visibility: Visibility,