From 8e6ee4363e1b4e4de0e43b1fa6f22c07637cc3b1 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 29 Mar 2023 12:01:58 +0200 Subject: [PATCH] Reduce clone calls --- crates/ruff/src/autofix/helpers.rs | 2 +- crates/ruff/src/checkers/ast/mod.rs | 575 +++++++++--------- crates/ruff/src/docstrings/definition.rs | 3 +- crates/ruff/src/docstrings/extraction.rs | 4 +- crates/ruff/src/docstrings/sections.rs | 4 +- crates/ruff/src/docstrings/styles.rs | 1 + crates/ruff/src/flake8_to_ruff/converter.rs | 2 +- crates/ruff/src/flake8_to_ruff/parser.rs | 2 +- crates/ruff/src/flake8_to_ruff/plugin.rs | 2 +- crates/ruff/src/jupyter/schema.rs | 6 +- crates/ruff/src/lex/docstring_detection.rs | 2 +- crates/ruff/src/noqa.rs | 20 +- crates/ruff/src/resolver.rs | 1 + crates/ruff/src/rule_selector.rs | 2 +- .../src/rules/flake8_annotations/rules.rs | 2 +- .../rules/useless_expression.rs | 2 +- .../src/rules/flake8_comprehensions/fixes.rs | 30 +- .../ruff/src/rules/flake8_debugger/types.rs | 2 +- .../src/rules/flake8_logging_format/rules.rs | 1 + crates/ruff/src/rules/flake8_pie/fixes.rs | 2 +- .../flake8_pyi/rules/prefix_type_params.rs | 2 +- .../flake8_pytest_style/rules/assertion.rs | 3 +- .../rules/unittest_assert.rs | 3 +- crates/ruff/src/rules/flake8_quotes/rules.rs | 40 +- .../ruff/src/rules/flake8_quotes/settings.rs | 2 +- crates/ruff/src/rules/flake8_return/branch.rs | 2 +- .../src/rules/flake8_simplify/rules/fix_if.rs | 2 +- .../rules/flake8_simplify/rules/fix_with.rs | 2 +- .../flake8_simplify/rules/key_in_dict.rs | 2 +- .../flake8_simplify/rules/yoda_conditions.rs | 2 +- .../flake8_tidy_imports/relative_imports.rs | 6 +- .../rules/flake8_unused_arguments/rules.rs | 16 +- .../rules/flake8_unused_arguments/types.rs | 5 +- crates/ruff/src/rules/isort/categorize.rs | 1 + crates/ruff/src/rules/isort/format.rs | 24 +- crates/ruff/src/rules/isort/mod.rs | 16 +- crates/ruff/src/rules/isort/sorting.rs | 2 +- crates/ruff/src/rules/isort/track.rs | 2 +- .../pycodestyle/rules/literal_comparisons.rs | 2 +- .../src/rules/pydocstyle/rules/not_missing.rs | 6 +- .../src/rules/pydocstyle/rules/sections.rs | 8 +- crates/ruff/src/rules/pyflakes/fixes.rs | 6 +- .../ruff/src/rules/pyflakes/rules/imports.rs | 2 +- .../rules/invalid_literal_comparisons.rs | 2 +- .../rules/pyflakes/rules/unused_variable.rs | 1 + .../rules/pylint/rules/bad_str_strip_call.rs | 8 +- .../pylint/rules/bad_string_format_type.rs | 8 +- .../pylint/rules/comparison_of_constant.rs | 2 +- crates/ruff/src/rules/pyupgrade/fixes.rs | 4 +- .../pyupgrade/rules/deprecated_mock_import.rs | 16 +- .../rules/pyupgrade/rules/format_literals.rs | 4 +- .../rules/pyupgrade/rules/native_literals.rs | 2 +- .../pyupgrade/rules/redundant_open_modes.rs | 17 +- .../rules/unnecessary_builtin_import.rs | 2 +- .../rules/unnecessary_future_import.rs | 2 +- .../pyupgrade/rules/use_pep604_annotation.rs | 1 + .../pyupgrade/rules/use_pep604_isinstance.rs | 2 +- .../pyupgrade/rules/useless_metaclass_type.rs | 2 +- .../rules/ruff/rules/asyncio_dangling_task.rs | 2 +- .../rules/collection_literal_concatenation.rs | 2 +- crates/ruff_cli/src/lib.rs | 1 + crates/ruff_diagnostics/src/violation.rs | 1 + .../ruff_python_ast/src/branch_detection.rs | 41 +- crates/ruff_python_ast/src/comparable.rs | 10 +- crates/ruff_python_ast/src/context.rs | 9 +- crates/ruff_python_ast/src/function_type.rs | 1 + crates/ruff_python_ast/src/logging.rs | 1 + crates/ruff_python_ast/src/scope.rs | 11 + .../src/source_code/generator.rs | 30 +- .../src/source_code/stylist.rs | 7 +- crates/ruff_python_ast/src/types.rs | 16 +- crates/ruff_python_ast/src/typing.rs | 4 +- crates/ruff_python_ast/src/visibility.rs | 6 +- 73 files changed, 550 insertions(+), 486 deletions(-) diff --git a/crates/ruff/src/autofix/helpers.rs b/crates/ruff/src/autofix/helpers.rs index a46553d4d218b6..a595dbb00d0d5e 100644 --- a/crates/ruff/src/autofix/helpers.rs +++ b/crates/ruff/src/autofix/helpers.rs @@ -327,7 +327,7 @@ pub fn remove_unused_imports<'a>( delete_stmt(stmt, parent, deleted, locator, indexer, stylist) } else { let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 9304069ec3822b..9db1769839160d 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -655,7 +655,7 @@ where synthetic_usage: None, typing_usage: None, range: Range::from(stmt), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -853,7 +853,7 @@ where synthetic_usage: Some((self.ctx.scope_id(), Range::from(alias))), typing_usage: None, range: Range::from(alias), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -883,7 +883,7 @@ where synthetic_usage: None, typing_usage: None, range: Range::from(alias), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -911,7 +911,7 @@ where }, typing_usage: None, range: Range::from(alias), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -1157,7 +1157,7 @@ where synthetic_usage: Some((self.ctx.scope_id(), Range::from(alias))), typing_usage: None, range: Range::from(alias), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -1191,7 +1191,7 @@ where synthetic_usage: None, typing_usage: None, range: Range::from(stmt), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -1271,7 +1271,7 @@ where }, typing_usage: None, range: Range::from(alias), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -1871,7 +1871,7 @@ where // Recurse. 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 { StmtKind::FunctionDef { body, @@ -1891,19 +1891,18 @@ where flake8_bugbear::rules::f_string_docstring(self, body); } let definition = docstrings::extraction::extract( - &self.ctx.visible_scope, + self.ctx.visible_scope, stmt, body, - &Documentable::Function, + Documentable::Function, ); if self.settings.rules.enabled(Rule::YieldInForLoop) { pyupgrade::rules::yield_in_for_loop(self, stmt); } - let scope = - transition_scope(&self.ctx.visible_scope, stmt, &Documentable::Function); + let scope = transition_scope(self.ctx.visible_scope, stmt, Documentable::Function); self.deferred.definitions.push(( definition, - scope.visibility.clone(), + scope.visibility, (self.ctx.scope_stack.clone(), self.ctx.parents.clone()), )); self.ctx.visible_scope = scope; @@ -1943,7 +1942,7 @@ where self.deferred.functions.push(( stmt, (self.ctx.scope_stack.clone(), self.ctx.parents.clone()), - self.ctx.visible_scope.clone(), + self.ctx.visible_scope, )); } StmtKind::ClassDef { @@ -1958,15 +1957,15 @@ where flake8_bugbear::rules::f_string_docstring(self, body); } let definition = docstrings::extraction::extract( - &self.ctx.visible_scope, + self.ctx.visible_scope, stmt, 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(( definition, - scope.visibility.clone(), + scope.visibility, (self.ctx.scope_stack.clone(), self.ctx.parents.clone()), )); self.ctx.visible_scope = scope; @@ -2136,7 +2135,7 @@ where synthetic_usage: None, typing_usage: None, range: Range::from(stmt), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -3928,7 +3927,7 @@ where synthetic_usage: None, typing_usage: None, range: Range::from(arg), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -3972,7 +3971,7 @@ where synthetic_usage: None, typing_usage: None, range: Range::from(pattern), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -4019,8 +4018,8 @@ impl<'a> Checker<'a> { let existing = &self.ctx.bindings[existing_binding_index]; let in_current_scope = stack_index == 0; if !existing.kind.is_builtin() - && existing.source.as_ref().map_or(true, |left| { - binding.source.as_ref().map_or(true, |right| { + && existing.source.map_or(true, |left| { + binding.source.map_or(true, |right| { !branch_detection::different_forks( left, right, @@ -4373,7 +4372,7 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: Range::from(expr), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -4394,7 +4393,7 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: Range::from(expr), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -4411,7 +4410,7 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: Range::from(expr), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -4477,7 +4476,7 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: Range::from(expr), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -4494,7 +4493,7 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: Range::from(expr), - source: Some(self.ctx.current_stmt().clone()), + source: Some(*self.ctx.current_stmt()), context: self.ctx.execution_context(), exceptions: self.ctx.exceptions(), }, @@ -4539,34 +4538,36 @@ impl<'a> Checker<'a> { }, docstring, }, - self.ctx.visible_scope.visibility.clone(), + self.ctx.visible_scope.visibility, (self.ctx.scope_stack.clone(), self.ctx.parents.clone()), )); docstring.is_some() } fn check_deferred_type_definitions(&mut self) { - self.deferred.type_definitions.reverse(); - while let Some((expr, (in_annotation, in_type_checking_block), (scopes, parents))) = - self.deferred.type_definitions.pop() - { - self.ctx.scope_stack = scopes; - self.ctx.parents = parents; - self.ctx.in_annotation = in_annotation; - self.ctx.in_type_checking_block = in_type_checking_block; - self.ctx.in_type_definition = true; - self.ctx.in_deferred_type_definition = true; - self.visit_expr(expr); - self.ctx.in_deferred_type_definition = false; - self.ctx.in_type_definition = false; + while !self.deferred.type_definitions.is_empty() { + let type_definitions = std::mem::take(&mut self.deferred.type_definitions); + for (expr, (in_annotation, in_type_checking_block), (scopes, parents)) in + type_definitions + { + self.ctx.scope_stack = scopes; + self.ctx.parents = parents; + self.ctx.in_annotation = in_annotation; + self.ctx.in_type_checking_block = in_type_checking_block; + self.ctx.in_type_definition = true; + self.ctx.in_deferred_type_definition = true; + self.visit_expr(expr); + 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) { - let mut type_definitions = std::mem::take(&mut self.deferred.string_type_definitions); - loop { + while !self.deferred.string_type_definitions.is_empty() { + let type_definitions = std::mem::take(&mut self.deferred.string_type_definitions); 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 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) { - self.deferred.functions.reverse(); - while let Some((stmt, (scopes, parents), visibility)) = self.deferred.functions.pop() { - self.ctx.scope_stack = scopes.clone(); - self.ctx.parents = parents.clone(); - self.ctx.visible_scope = visibility; - - match &stmt.node { - StmtKind::FunctionDef { body, args, .. } - | StmtKind::AsyncFunctionDef { body, args, .. } => { - self.visit_arguments(args); - self.visit_body(body); + while !self.deferred.functions.is_empty() { + let deferred_functions = std::mem::take(&mut self.deferred.functions); + for (stmt, (scopes, parents), visibility) in deferred_functions { + let scope_snapshot = scopes.snapshot(); + let parents_snapshot = parents.len(); + self.ctx.scope_stack = scopes; + self.ctx.parents = parents; + self.ctx.visible_scope = visibility; + + match &stmt.node { + StmtKind::FunctionDef { body, args, .. } + | StmtKind::AsyncFunctionDef { body, args, .. } => { + self.visit_arguments(args); + 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) { - self.deferred.lambdas.reverse(); - while let Some((expr, (scopes, parents))) = self.deferred.lambdas.pop() { - self.ctx.scope_stack = scopes.clone(); - self.ctx.parents = parents.clone(); - - if let ExprKind::Lambda { args, body } = &expr.node { - self.visit_arguments(args); - self.visit_expr(body); - } else { - unreachable!("Expected ExprKind::Lambda"); - } + while !self.deferred.lambdas.is_empty() { + let lambdas = std::mem::take(&mut self.deferred.lambdas); + for (expr, (scopes, parents)) in lambdas { + let scope_snapshot = scopes.snapshot(); + let parents_snapshot = parents.len(); + + self.ctx.scope_stack = scopes; + self.ctx.parents = parents; + + if let ExprKind::Lambda { args, body } = &expr.node { + self.visit_arguments(args); + self.visit_expr(body); + } else { + unreachable!("Expected ExprKind::Lambda"); + } - 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_assignments(&mut self) { - self.deferred.assignments.reverse(); - while let Some((scopes, ..)) = self.deferred.assignments.pop() { - let mut scopes_iter = scopes.iter(); - let scope_index = *scopes_iter.next().unwrap(); - let parent_scope_index = *scopes_iter.next().unwrap(); - - // pyflakes - if self.settings.rules.enabled(Rule::UnusedVariable) { - pyflakes::rules::unused_variable(self, scope_index); - } - if self.settings.rules.enabled(Rule::UnusedAnnotation) { - pyflakes::rules::unused_annotation(self, scope_index); - } + while !self.deferred.assignments.is_empty() { + let assignments = std::mem::take(&mut self.deferred.assignments); + for (scopes, ..) in assignments { + let mut scopes_iter = scopes.iter(); + let scope_index = *scopes_iter.next().unwrap(); + let parent_scope_index = *scopes_iter.next().unwrap(); - if !self.is_stub { - // flake8-unused-arguments - if self.settings.rules.any_enabled(&[ - Rule::UnusedFunctionArgument, - Rule::UnusedMethodArgument, - Rule::UnusedClassMethodArgument, - Rule::UnusedStaticMethodArgument, - Rule::UnusedLambdaArgument, - ]) { - self.diagnostics - .extend(flake8_unused_arguments::rules::unused_arguments( - self, - &self.ctx.scopes[parent_scope_index], - &self.ctx.scopes[scope_index], - &self.ctx.bindings, - )); + // pyflakes + if self.settings.rules.enabled(Rule::UnusedVariable) { + pyflakes::rules::unused_variable(self, scope_index); + } + if self.settings.rules.enabled(Rule::UnusedAnnotation) { + pyflakes::rules::unused_annotation(self, scope_index); + } + + if !self.is_stub { + // flake8-unused-arguments + if self.settings.rules.any_enabled(&[ + Rule::UnusedFunctionArgument, + Rule::UnusedMethodArgument, + Rule::UnusedClassMethodArgument, + Rule::UnusedStaticMethodArgument, + Rule::UnusedLambdaArgument, + ]) { + self.diagnostics + .extend(flake8_unused_arguments::rules::unused_arguments( + self, + &self.ctx.scopes[parent_scope_index], + &self.ctx.scopes[scope_index], + &self.ctx.bindings, + )); + } } } } } fn check_deferred_for_loops(&mut self) { - self.deferred.for_loops.reverse(); - while let Some((stmt, (scopes, parents))) = self.deferred.for_loops.pop() { - self.ctx.scope_stack = scopes.clone(); - self.ctx.parents = parents.clone(); + while !self.deferred.for_loops.is_empty() { + let for_loops = std::mem::take(&mut self.deferred.for_loops); - 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); + for (stmt, (scopes, parents)) in for_loops { + self.ctx.scope_stack = scopes; + self.ctx.parents = parents; + + 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) => { if fix.content.is_empty() || fix.content == "pass" { - self.deletions.insert(defined_by.clone()); + self.deletions.insert(*defined_by); } Some(fix) } @@ -5167,181 +5193,182 @@ impl<'a> Checker<'a> { ]); let mut overloaded_name: Option = None; - self.deferred.definitions.reverse(); - while let Some((definition, visibility, (scopes, parents))) = - self.deferred.definitions.pop() - { - self.ctx.scope_stack = scopes.clone(); - self.ctx.parents = parents.clone(); - - // flake8-annotations - if enforce_annotations { - // TODO(charlie): This should be even stricter, in that an overload - // implementation should come immediately after the overloaded - // interfaces, without any AST nodes in between. Right now, we - // only error when traversing definition boundaries (functions, - // classes, etc.). - if !overloaded_name.map_or(false, |overloaded_name| { - flake8_annotations::helpers::is_overload_impl( - self, - &definition, - &overloaded_name, - ) - }) { - self.diagnostics - .extend(flake8_annotations::rules::definition( + while !self.deferred.definitions.is_empty() { + let definitions = std::mem::take(&mut self.deferred.definitions); + for (definition, visibility, (scopes, parents)) in definitions { + self.ctx.scope_stack = scopes; + self.ctx.parents = parents; + + // flake8-annotations + if enforce_annotations { + // TODO(charlie): This should be even stricter, in that an overload + // implementation should come immediately after the overloaded + // interfaces, without any AST nodes in between. Right now, we + // only error when traversing definition boundaries (functions, + // classes, etc.). + if !overloaded_name.map_or(false, |overloaded_name| { + flake8_annotations::helpers::is_overload_impl( self, &definition, - &visibility, - )); + &overloaded_name, + ) + }) { + self.diagnostics + .extend(flake8_annotations::rules::definition( + self, + &definition, + visibility, + )); + } + overloaded_name = + flake8_annotations::helpers::overloaded_name(self, &definition); } - overloaded_name = flake8_annotations::helpers::overloaded_name(self, &definition); - } - if self.is_stub { - if self.settings.rules.enabled(Rule::DocstringInStub) { - flake8_pyi::rules::docstring_in_stubs(self, definition.docstring); + if self.is_stub { + if self.settings.rules.enabled(Rule::DocstringInStub) { + flake8_pyi::rules::docstring_in_stubs(self, definition.docstring); + } } - } - // pydocstyle - if enforce_docstrings { - if pydocstyle::helpers::should_ignore_definition( - self, - &definition, - &self.settings.pydocstyle.ignore_decorators, - ) { - continue; - } + // pydocstyle + if enforce_docstrings { + if pydocstyle::helpers::should_ignore_definition( + self, + &definition, + &self.settings.pydocstyle.ignore_decorators, + ) { + continue; + } - if definition.docstring.is_none() { - pydocstyle::rules::not_missing(self, &definition, &visibility); - continue; - } + if definition.docstring.is_none() { + 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()), - )); + // 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!( + if pydocstyle::helpers::should_ignore_docstring(contents) { + warn_user!( "Docstring at {}:{}:{} contains implicit string concatenation; ignoring...", relativize_path(self.path), expr.location.row(), expr.location.column() + 1 ); - continue; - } + continue; + } - // SAFETY: Safe for docstrings that pass `should_ignore_docstring`. - let body = str::raw_contents(contents).unwrap(); - let docstring = Docstring { - kind: definition.kind, - expr, - contents, - indentation, - body, - }; + // SAFETY: Safe for docstrings that pass `should_ignore_docstring`. + let body = str::raw_contents(contents).unwrap(); + let docstring = Docstring { + kind: definition.kind, + expr, + contents, + indentation, + body, + }; - if !pydocstyle::rules::not_empty(self, &docstring) { - continue; - } + if !pydocstyle::rules::not_empty(self, &docstring) { + continue; + } - if self.settings.rules.enabled(Rule::FitsOnOneLine) { - pydocstyle::rules::one_liner(self, &docstring); - } - if self.settings.rules.any_enabled(&[ - Rule::NoBlankLineBeforeFunction, - Rule::NoBlankLineAfterFunction, - ]) { - pydocstyle::rules::blank_before_after_function(self, &docstring); - } - if self.settings.rules.any_enabled(&[ - Rule::OneBlankLineBeforeClass, - Rule::OneBlankLineAfterClass, - Rule::BlankLineBeforeClass, - ]) { - pydocstyle::rules::blank_before_after_class(self, &docstring); - } - if self.settings.rules.enabled(Rule::BlankLineAfterSummary) { - pydocstyle::rules::blank_after_summary(self, &docstring); - } - if self.settings.rules.any_enabled(&[ - Rule::IndentWithSpaces, - Rule::UnderIndentation, - Rule::OverIndentation, - ]) { - pydocstyle::rules::indent(self, &docstring); - } - if self.settings.rules.enabled(Rule::NewLineAfterLastParagraph) { - pydocstyle::rules::newline_after_last_paragraph(self, &docstring); - } - if self.settings.rules.enabled(Rule::SurroundingWhitespace) { - pydocstyle::rules::no_surrounding_whitespace(self, &docstring); - } - if self.settings.rules.any_enabled(&[ - Rule::MultiLineSummaryFirstLine, - Rule::MultiLineSummarySecondLine, - ]) { - pydocstyle::rules::multi_line_summary_start(self, &docstring); - } - if self.settings.rules.enabled(Rule::TripleSingleQuotes) { - pydocstyle::rules::triple_quotes(self, &docstring); - } - if self.settings.rules.enabled(Rule::EscapeSequenceInDocstring) { - pydocstyle::rules::backslashes(self, &docstring); - } - if self.settings.rules.enabled(Rule::EndsInPeriod) { - pydocstyle::rules::ends_with_period(self, &docstring); - } - if self.settings.rules.enabled(Rule::NonImperativeMood) { - pydocstyle::rules::non_imperative_mood( - self, - &docstring, - &self.settings.pydocstyle.property_decorators, - ); - } - if self.settings.rules.enabled(Rule::NoSignature) { - pydocstyle::rules::no_signature(self, &docstring); - } - if self.settings.rules.enabled(Rule::FirstLineCapitalized) { - pydocstyle::rules::capitalized(self, &docstring); - } - if self.settings.rules.enabled(Rule::DocstringStartsWithThis) { - pydocstyle::rules::starts_with_this(self, &docstring); - } - if self.settings.rules.enabled(Rule::EndsInPunctuation) { - pydocstyle::rules::ends_with_punctuation(self, &docstring); - } - if self.settings.rules.enabled(Rule::OverloadWithDocstring) { - pydocstyle::rules::if_needed(self, &docstring); - } - if self.settings.rules.any_enabled(&[ - Rule::MultiLineSummaryFirstLine, - Rule::SectionNotOverIndented, - Rule::SectionUnderlineNotOverIndented, - Rule::CapitalizeSectionName, - Rule::NewLineAfterSectionName, - Rule::DashedUnderlineAfterSection, - Rule::SectionUnderlineAfterName, - Rule::SectionUnderlineMatchesSectionLength, - Rule::NoBlankLineAfterSection, - Rule::NoBlankLineBeforeSection, - Rule::BlankLinesBetweenHeaderAndContent, - Rule::BlankLineAfterLastSection, - Rule::EmptyDocstringSection, - Rule::SectionNameEndsInColon, - Rule::UndocumentedParam, - ]) { - pydocstyle::rules::sections( - self, - &docstring, - self.settings.pydocstyle.convention.as_ref(), - ); + if self.settings.rules.enabled(Rule::FitsOnOneLine) { + pydocstyle::rules::one_liner(self, &docstring); + } + if self.settings.rules.any_enabled(&[ + Rule::NoBlankLineBeforeFunction, + Rule::NoBlankLineAfterFunction, + ]) { + pydocstyle::rules::blank_before_after_function(self, &docstring); + } + if self.settings.rules.any_enabled(&[ + Rule::OneBlankLineBeforeClass, + Rule::OneBlankLineAfterClass, + Rule::BlankLineBeforeClass, + ]) { + pydocstyle::rules::blank_before_after_class(self, &docstring); + } + if self.settings.rules.enabled(Rule::BlankLineAfterSummary) { + pydocstyle::rules::blank_after_summary(self, &docstring); + } + if self.settings.rules.any_enabled(&[ + Rule::IndentWithSpaces, + Rule::UnderIndentation, + Rule::OverIndentation, + ]) { + pydocstyle::rules::indent(self, &docstring); + } + if self.settings.rules.enabled(Rule::NewLineAfterLastParagraph) { + pydocstyle::rules::newline_after_last_paragraph(self, &docstring); + } + if self.settings.rules.enabled(Rule::SurroundingWhitespace) { + pydocstyle::rules::no_surrounding_whitespace(self, &docstring); + } + if self.settings.rules.any_enabled(&[ + Rule::MultiLineSummaryFirstLine, + Rule::MultiLineSummarySecondLine, + ]) { + pydocstyle::rules::multi_line_summary_start(self, &docstring); + } + if self.settings.rules.enabled(Rule::TripleSingleQuotes) { + pydocstyle::rules::triple_quotes(self, &docstring); + } + if self.settings.rules.enabled(Rule::EscapeSequenceInDocstring) { + pydocstyle::rules::backslashes(self, &docstring); + } + if self.settings.rules.enabled(Rule::EndsInPeriod) { + pydocstyle::rules::ends_with_period(self, &docstring); + } + if self.settings.rules.enabled(Rule::NonImperativeMood) { + pydocstyle::rules::non_imperative_mood( + self, + &docstring, + &self.settings.pydocstyle.property_decorators, + ); + } + if self.settings.rules.enabled(Rule::NoSignature) { + pydocstyle::rules::no_signature(self, &docstring); + } + if self.settings.rules.enabled(Rule::FirstLineCapitalized) { + pydocstyle::rules::capitalized(self, &docstring); + } + if self.settings.rules.enabled(Rule::DocstringStartsWithThis) { + pydocstyle::rules::starts_with_this(self, &docstring); + } + if self.settings.rules.enabled(Rule::EndsInPunctuation) { + pydocstyle::rules::ends_with_punctuation(self, &docstring); + } + if self.settings.rules.enabled(Rule::OverloadWithDocstring) { + pydocstyle::rules::if_needed(self, &docstring); + } + if self.settings.rules.any_enabled(&[ + Rule::MultiLineSummaryFirstLine, + Rule::SectionNotOverIndented, + Rule::SectionUnderlineNotOverIndented, + Rule::CapitalizeSectionName, + Rule::NewLineAfterSectionName, + Rule::DashedUnderlineAfterSection, + Rule::SectionUnderlineAfterName, + Rule::SectionUnderlineMatchesSectionLength, + Rule::NoBlankLineAfterSection, + Rule::NoBlankLineBeforeSection, + Rule::BlankLinesBetweenHeaderAndContent, + Rule::BlankLineAfterLastSection, + Rule::EmptyDocstringSection, + Rule::SectionNameEndsInColon, + Rule::UndocumentedParam, + ]) { + pydocstyle::rules::sections( + self, + &docstring, + self.settings.pydocstyle.convention.as_ref(), + ); + } } } } diff --git a/crates/ruff/src/docstrings/definition.rs b/crates/ruff/src/docstrings/definition.rs index d1a2a647417f67..3da648d0b46637 100644 --- a/crates/ruff/src/docstrings/definition.rs +++ b/crates/ruff/src/docstrings/definition.rs @@ -29,12 +29,13 @@ pub struct Docstring<'a> { pub indentation: &'a str, } +#[derive(Copy, Clone)] pub enum Documentable { Class, 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 { Documentable::Function => VisibleScope { modifier: Modifier::Function, diff --git a/crates/ruff/src/docstrings/extraction.rs b/crates/ruff/src/docstrings/extraction.rs index 0bc42cfce08327..8d1bae28355a73 100644 --- a/crates/ruff/src/docstrings/extraction.rs +++ b/crates/ruff/src/docstrings/extraction.rs @@ -28,10 +28,10 @@ pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> { /// Extract a `Definition` from the AST node defined by a `Stmt`. pub fn extract<'a>( - scope: &VisibleScope, + scope: VisibleScope, stmt: &'a Stmt, body: &'a [Stmt], - kind: &Documentable, + kind: Documentable, ) -> Definition<'a> { let expr = docstring_from(body); match kind { diff --git a/crates/ruff/src/docstrings/sections.rs b/crates/ruff/src/docstrings/sections.rs index d798a12637d427..ab1d6930d0ebeb 100644 --- a/crates/ruff/src/docstrings/sections.rs +++ b/crates/ruff/src/docstrings/sections.rs @@ -129,7 +129,7 @@ pub(crate) struct SectionContext<'a> { pub(crate) original_index: usize, } -fn suspected_as_section(line: &str, style: &SectionStyle) -> Option { +fn suspected_as_section(line: &str, style: SectionStyle) -> Option { if let Some(kind) = SectionKind::from_str(whitespace::leading_words(line)) { if style.sections().contains(&kind) { return Some(kind); @@ -168,7 +168,7 @@ fn is_docstring_section(context: &SectionContext) -> bool { /// Extract all `SectionContext` values from a docstring. pub(crate) fn section_contexts<'a>( lines: &'a [&'a str], - style: &SectionStyle, + style: SectionStyle, ) -> Vec> { let mut contexts = vec![]; for (kind, lineno) in lines diff --git a/crates/ruff/src/docstrings/styles.rs b/crates/ruff/src/docstrings/styles.rs index a31d27a99790f0..b6a1b6dbaf0ba0 100644 --- a/crates/ruff/src/docstrings/styles.rs +++ b/crates/ruff/src/docstrings/styles.rs @@ -2,6 +2,7 @@ use crate::docstrings::google::GOOGLE_SECTIONS; use crate::docstrings::numpy::NUMPY_SECTIONS; use crate::docstrings::sections::SectionKind; +#[derive(Copy, Clone)] pub(crate) enum SectionStyle { Numpy, Google, diff --git a/crates/ruff/src/flake8_to_ruff/converter.rs b/crates/ruff/src/flake8_to_ruff/converter.rs index 7d7c40827ada76..8e54ae57bcfc71 100644 --- a/crates/ruff/src/flake8_to_ruff/converter.rs +++ b/crates/ruff/src/flake8_to_ruff/converter.rs @@ -416,7 +416,7 @@ pub fn convert( if let Some(src_paths) = &isort.src_paths { match options.src.as_mut() { Some(src) => { - src.extend(src_paths.clone()); + src.extend_from_slice(src_paths); } None => { options.src = Some(src_paths.clone()); diff --git a/crates/ruff/src/flake8_to_ruff/parser.rs b/crates/ruff/src/flake8_to_ruff/parser.rs index d7407fce7c49b2..3e44adab5a904e 100644 --- a/crates/ruff/src/flake8_to_ruff/parser.rs +++ b/crates/ruff/src/flake8_to_ruff/parser.rs @@ -54,7 +54,7 @@ struct Token { src: String, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum TokenType { Code, File, diff --git a/crates/ruff/src/flake8_to_ruff/plugin.rs b/crates/ruff/src/flake8_to_ruff/plugin.rs index 3283b0b2800851..93e39d6b03b94f 100644 --- a/crates/ruff/src/flake8_to_ruff/plugin.rs +++ b/crates/ruff/src/flake8_to_ruff/plugin.rs @@ -7,7 +7,7 @@ use anyhow::anyhow; use crate::registry::Linter; use crate::rule_selector::RuleSelector; -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] pub enum Plugin { Flake82020, Flake8Annotations, diff --git a/crates/ruff/src/jupyter/schema.rs b/crates/ruff/src/jupyter/schema.rs index d9e9c80a2137ad..33b120f7ee8aaa 100644 --- a/crates/ruff/src/jupyter/schema.rs +++ b/crates/ruff/src/jupyter/schema.rs @@ -226,7 +226,7 @@ pub enum CodemirrorMode { } /// String identifying the type of cell. -#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Copy, Clone)] pub enum CellType { #[serde(rename = "code")] Code, @@ -236,14 +236,14 @@ pub enum CellType { Raw, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Copy, Clone)] pub enum ScrolledEnum { #[serde(rename = "auto")] Auto, } /// Type of cell output. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Copy, Clone)] pub enum OutputType { #[serde(rename = "display_data")] DisplayData, diff --git a/crates/ruff/src/lex/docstring_detection.rs b/crates/ruff/src/lex/docstring_detection.rs index 6bbed700f969c7..2178034fcd99a8 100644 --- a/crates/ruff/src/lex/docstring_detection.rs +++ b/crates/ruff/src/lex/docstring_detection.rs @@ -6,7 +6,7 @@ use rustpython_parser::Tok; -#[derive(Default)] +#[derive(Default, Copy, Clone)] enum State { // Start of the module: first string gets marked as a docstring. #[default] diff --git a/crates/ruff/src/noqa.rs b/crates/ruff/src/noqa.rs index 089ff45b19f36b..397054f9ea6cb8 100644 --- a/crates/ruff/src/noqa.rs +++ b/crates/ruff/src/noqa.rs @@ -188,7 +188,7 @@ pub fn add_noqa( contents: &str, commented_lines: &[usize], noqa_line_for: &IntMap, - line_ending: &LineEnding, + line_ending: LineEnding, ) -> Result { let (count, output) = add_noqa_inner( diagnostics, @@ -206,7 +206,7 @@ fn add_noqa_inner( contents: &str, commented_lines: &[usize], noqa_line_for: &IntMap, - line_ending: &LineEnding, + line_ending: LineEnding, ) -> (usize, String) { // Map of line number to set of (non-ignored) diagnostic codes that are triggered on that line. let mut matches_by_line: FxHashMap = FxHashMap::default(); @@ -288,7 +288,7 @@ fn add_noqa_inner( match matches_by_line.get(&lineno) { None => { output.push_str(line); - output.push_str(line_ending); + output.push_str(&line_ending); } Some(rules) => { match extract_noqa_directive(line) { @@ -301,13 +301,13 @@ fn add_noqa_inner( // Add codes. push_codes(&mut output, rules.iter().map(|rule| rule.noqa_code())); - output.push_str(line_ending); + output.push_str(&line_ending); count += 1; } Directive::All(..) => { // Leave the line as-is. output.push_str(line); - output.push_str(line_ending); + output.push_str(&line_ending); } Directive::Codes(_, start_byte, _, existing, _) => { // Reconstruct the line based on the preserved rule codes. @@ -331,7 +331,7 @@ fn add_noqa_inner( ); output.push_str(&formatted); - output.push_str(line_ending); + output.push_str(&line_ending); // Only count if the new line is an actual edit. if formatted != line { @@ -395,7 +395,7 @@ mod tests { contents, &commented_lines, &noqa_line_for, - &LineEnding::Lf, + LineEnding::Lf, ); assert_eq!(count, 0); assert_eq!(output, format!("{contents}\n")); @@ -414,7 +414,7 @@ mod tests { contents, &commented_lines, &noqa_line_for, - &LineEnding::Lf, + LineEnding::Lf, ); assert_eq!(count, 1); assert_eq!(output, "x = 1 # noqa: F841\n"); @@ -439,7 +439,7 @@ mod tests { contents, &commented_lines, &noqa_line_for, - &LineEnding::Lf, + LineEnding::Lf, ); assert_eq!(count, 1); assert_eq!(output, "x = 1 # noqa: E741, F841\n"); @@ -464,7 +464,7 @@ mod tests { contents, &commented_lines, &noqa_line_for, - &LineEnding::Lf, + LineEnding::Lf, ); assert_eq!(count, 0); assert_eq!(output, "x = 1 # noqa\n"); diff --git a/crates/ruff/src/resolver.rs b/crates/ruff/src/resolver.rs index c2bc86fc89f01e..6ddbccefb10c2b 100644 --- a/crates/ruff/src/resolver.rs +++ b/crates/ruff/src/resolver.rs @@ -41,6 +41,7 @@ impl PyprojectDiscovery { } /// The strategy for resolving file paths in a `pyproject.toml`. +#[derive(Copy, Clone)] pub enum Relativity { /// Resolve file paths relative to the current working directory. Cwd, diff --git a/crates/ruff/src/rule_selector.rs b/crates/ruff/src/rule_selector.rs index 55f34add8e6ea4..55d8efaf0602c9 100644 --- a/crates/ruff/src/rule_selector.rs +++ b/crates/ruff/src/rule_selector.rs @@ -265,7 +265,7 @@ impl RuleSelector { } } -#[derive(EnumIter, PartialEq, Eq, PartialOrd, Ord)] +#[derive(EnumIter, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] pub(crate) enum Specificity { All, LinterGroup, diff --git a/crates/ruff/src/rules/flake8_annotations/rules.rs b/crates/ruff/src/rules/flake8_annotations/rules.rs index 2a2e72a67d93ba..776a392ffce5f7 100644 --- a/crates/ruff/src/rules/flake8_annotations/rules.rs +++ b/crates/ruff/src/rules/flake8_annotations/rules.rs @@ -455,7 +455,7 @@ fn check_dynamically_typed( pub fn definition( checker: &Checker, definition: &Definition, - visibility: &Visibility, + visibility: Visibility, ) -> Vec { // TODO(charlie): Consider using the AST directly here rather than `Definition`. // We could adhere more closely to `flake8-annotations` by defining public diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs index 8d19837ec1fd75..842d97e325741b 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs @@ -7,7 +7,7 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Kind { Expression, Attribute, diff --git a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs index 08d005046287c0..f80c0ac99dd879 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs @@ -61,7 +61,7 @@ pub fn fix_unnecessary_generator_list( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -108,7 +108,7 @@ pub fn fix_unnecessary_generator_set( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -182,7 +182,7 @@ pub fn fix_unnecessary_generator_dict( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -237,7 +237,7 @@ pub fn fix_unnecessary_list_comprehension_set( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -293,7 +293,7 @@ pub fn fix_unnecessary_list_comprehension_dict( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -387,7 +387,7 @@ pub fn fix_unnecessary_literal_set( } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -460,7 +460,7 @@ pub fn fix_unnecessary_literal_dict( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -576,7 +576,7 @@ pub fn fix_unnecessary_collection_call( }; let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -635,7 +635,7 @@ pub fn fix_unnecessary_literal_within_tuple_call( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -696,7 +696,7 @@ pub fn fix_unnecessary_literal_within_list_call( })); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -725,7 +725,7 @@ pub fn fix_unnecessary_list_call( body.value = arg.value.clone(); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -854,7 +854,7 @@ pub fn fix_unnecessary_call_around_sorted( } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -893,7 +893,7 @@ pub fn fix_unnecessary_double_cast_or_process( outer_call.args = inner_call.clone(); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -989,7 +989,7 @@ pub fn fix_unnecessary_comprehension( } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -1142,7 +1142,7 @@ pub fn fix_unnecessary_map( } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/flake8_debugger/types.rs b/crates/ruff/src/rules/flake8_debugger/types.rs index 8928516ed87f0a..ab3485a3a60641 100644 --- a/crates/ruff/src/rules/flake8_debugger/types.rs +++ b/crates/ruff/src/rules/flake8_debugger/types.rs @@ -1,4 +1,4 @@ -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum DebuggerUsingType { Call(String), Import(String), diff --git a/crates/ruff/src/rules/flake8_logging_format/rules.rs b/crates/ruff/src/rules/flake8_logging_format/rules.rs index ba4ea7087ca1f8..b2b9557351bae8 100644 --- a/crates/ruff/src/rules/flake8_logging_format/rules.rs +++ b/crates/ruff/src/rules/flake8_logging_format/rules.rs @@ -125,6 +125,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) { } } +#[derive(Copy, Clone)] enum LoggingCallType { /// Logging call with a level method, e.g., `logging.info`. LevelCall(LoggingLevel), diff --git a/crates/ruff/src/rules/flake8_pie/fixes.rs b/crates/ruff/src/rules/flake8_pie/fixes.rs index 217c82cb8a14d2..bc7615a53b3454 100644 --- a/crates/ruff/src/rules/flake8_pie/fixes.rs +++ b/crates/ruff/src/rules/flake8_pie/fixes.rs @@ -36,7 +36,7 @@ pub fn fix_unnecessary_comprehension_any_all( } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs b/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs index 8edd285fc2e12c..7bd2f50c760ce7 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs @@ -8,7 +8,7 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum VarKind { TypeVar, ParamSpec, diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index b6d7b150eab6b3..d5bcfd20b2bc30 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -247,6 +247,7 @@ pub fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs index 8c5a100a24ef33..9ce60532c7fc7c 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs @@ -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 /// `unittest` module. Note: any variants that can't be replaced with plain /// `assert` statements are commented out. +#[derive(Copy, Clone)] pub enum UnittestAssert { AlmostEqual, AlmostEquals, @@ -258,7 +259,7 @@ impl UnittestAssert { Ok(args_map) } - pub fn generate_assert(&self, args: &[Expr], keywords: &[Keyword]) -> Result { + pub fn generate_assert(self, args: &[Expr], keywords: &[Keyword]) -> Result { let args = self.args_map(args, keywords)?; match self { UnittestAssert::True | UnittestAssert::False => { diff --git a/crates/ruff/src/rules/flake8_quotes/rules.rs b/crates/ruff/src/rules/flake8_quotes/rules.rs index 051e4ddc40e6d3..859a4887885c0b 100644 --- a/crates/ruff/src/rules/flake8_quotes/rules.rs +++ b/crates/ruff/src/rules/flake8_quotes/rules.rs @@ -185,35 +185,35 @@ impl AlwaysAutofixableViolation for AvoidableEscapedQuote { } } -const fn good_single(quote: &Quote) -> char { +const fn good_single(quote: Quote) -> char { match quote { Quote::Single => '\'', Quote::Double => '"', } } -const fn bad_single(quote: &Quote) -> char { +const fn bad_single(quote: Quote) -> char { match quote { Quote::Double => '\'', Quote::Single => '"', } } -const fn good_multiline(quote: &Quote) -> &str { +const fn good_multiline(quote: Quote) -> &'static str { match quote { Quote::Single => "'''", Quote::Double => "\"\"\"", } } -const fn good_multiline_ending(quote: &Quote) -> &str { +const fn good_multiline_ending(quote: Quote) -> &'static str { match quote { Quote::Single => "'\"\"\"", Quote::Double => "\"'''", } } -const fn good_docstring(quote: &Quote) -> &str { +const fn good_docstring(quote: Quote) -> &'static str { match quote { Quote::Single => "'", Quote::Double => "\"", @@ -270,21 +270,21 @@ fn docstring( if trivia .raw_text - .contains(good_docstring("es_settings.docstring_quotes)) + .contains(good_docstring(quotes_settings.docstring_quotes)) { return None; } let mut diagnostic = Diagnostic::new( BadQuotesDocstring { - quote: quotes_settings.docstring_quotes.clone(), + quote: quotes_settings.docstring_quotes, }, Range::new(start, end), ); if autofix.into() && settings.rules.should_fix(Rule::BadQuotesDocstring) { 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 quote = good_docstring("es_settings.docstring_quotes).repeat(quote_count); + let quote = good_docstring(quotes_settings.docstring_quotes).repeat(quote_count); let mut fixed_contents = String::with_capacity(trivia.prefix.len() + string_contents.len() + quote.len() * 2); fixed_contents.push_str(trivia.prefix); @@ -323,12 +323,12 @@ fn strings( return false; } - if trivia.last_quote_char == good_single("es_settings.inline_quotes) { + if trivia.last_quote_char == good_single(quotes_settings.inline_quotes) { return false; } let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1]; - string_contents.contains(good_single("es_settings.inline_quotes)) + string_contents.contains(good_single(quotes_settings.inline_quotes)) }); 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 trivia .raw_text - .contains(good_multiline("es_settings.multiline_quotes)) + .contains(good_multiline(quotes_settings.multiline_quotes)) { continue; } @@ -344,21 +344,21 @@ fn strings( // If our string ends with a known good ending, then ignore it. if trivia .raw_text - .ends_with(good_multiline_ending("es_settings.multiline_quotes)) + .ends_with(good_multiline_ending(quotes_settings.multiline_quotes)) { continue; } let mut diagnostic = Diagnostic::new( BadQuotesMultilineString { - quote: quotes_settings.multiline_quotes.clone(), + quote: quotes_settings.multiline_quotes, }, Range::new(*start, *end), ); if autofix.into() && settings.rules.should_fix(Rule::BadQuotesMultilineString) { let string_contents = &trivia.raw_text[3..trivia.raw_text.len() - 3]; - let quote = good_multiline("es_settings.multiline_quotes); + let quote = good_multiline(quotes_settings.multiline_quotes); let mut fixed_contents = String::with_capacity( 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]; // If we're using the preferred quotation type, check for escapes. - if trivia.last_quote_char == good_single("es_settings.inline_quotes) { + if trivia.last_quote_char == good_single(quotes_settings.inline_quotes) { if !quotes_settings.avoid_escape || trivia.prefix.contains('r') || trivia.prefix.contains('R') @@ -381,13 +381,13 @@ fn strings( continue; } - if string_contents.contains(good_single("es_settings.inline_quotes)) - && !string_contents.contains(bad_single("es_settings.inline_quotes)) + if string_contents.contains(good_single(quotes_settings.inline_quotes)) + && !string_contents.contains(bad_single(quotes_settings.inline_quotes)) { let mut diagnostic = Diagnostic::new(AvoidableEscapedQuote, Range::new(*start, *end)); if autofix.into() && settings.rules.should_fix(Rule::AvoidableEscapedQuote) { - let quote = bad_single("es_settings.inline_quotes); + let quote = bad_single(quotes_settings.inline_quotes); let mut fixed_contents = String::with_capacity(trivia.prefix.len() + string_contents.len() + 2); @@ -441,12 +441,12 @@ fn strings( if !relax_quote { let mut diagnostic = Diagnostic::new( BadQuotesInlineString { - quote: quotes_settings.inline_quotes.clone(), + quote: quotes_settings.inline_quotes, }, Range::new(*start, *end), ); if autofix.into() && settings.rules.should_fix(Rule::BadQuotesInlineString) { - let quote = good_single("es_settings.inline_quotes); + let quote = good_single(quotes_settings.inline_quotes); let mut fixed_contents = String::with_capacity(trivia.prefix.len() + string_contents.len() + 2); fixed_contents.push_str(trivia.prefix); diff --git a/crates/ruff/src/rules/flake8_quotes/settings.rs b/crates/ruff/src/rules/flake8_quotes/settings.rs index 7ea0d99d7bdee4..b77fde3b440237 100644 --- a/crates/ruff/src/rules/flake8_quotes/settings.rs +++ b/crates/ruff/src/rules/flake8_quotes/settings.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; 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")] pub enum Quote { /// Use single quotes. diff --git a/crates/ruff/src/rules/flake8_return/branch.rs b/crates/ruff/src/rules/flake8_return/branch.rs index a655800a7ac10b..b1aa9e86bf304d 100644 --- a/crates/ruff/src/rules/flake8_return/branch.rs +++ b/crates/ruff/src/rules/flake8_return/branch.rs @@ -1,6 +1,6 @@ use std::fmt; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Branch { Elif, Else, diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs index aba162550a8dba..252de4f18aa47f 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs @@ -114,7 +114,7 @@ pub(crate) fn fix_nested_if_statements( outer_if.body = inner_if.body.clone(); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..Default::default() }; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs index dabacb449871ad..952b59c01e2a8f 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs @@ -78,7 +78,7 @@ pub(crate) fn fix_multiple_with_statements( outer_with.body = inner_with.body.clone(); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs index d8f9c3ec9a5dfa..9dea6d6f9b5e73 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -43,7 +43,7 @@ fn get_value_content_for_key_in_dict( let attribute = match_attribute(&mut call.func)?; let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs index 01ec44e24619a5..37335ed6a62079 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs @@ -123,7 +123,7 @@ fn reverse_comparison(expr: &Expr, locator: &Locator, stylist: &Stylist) -> Resu }; let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs b/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs index 86b27f40134129..f0db904fd240fd 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs @@ -14,7 +14,9 @@ use crate::registry::AsRule; 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")] pub enum Strictness { /// Ban imports that extend into the parent module or beyond. @@ -166,7 +168,7 @@ pub fn banned_relative_import( if level? > &strictness_level { let mut diagnostic = Diagnostic::new( RelativeImports { - strictness: strictness.clone(), + strictness: *strictness, }, Range::from(stmt), ); diff --git a/crates/ruff/src/rules/flake8_unused_arguments/rules.rs b/crates/ruff/src/rules/flake8_unused_arguments/rules.rs index 01a4aaf7cf8eb6..6d7a37ac3174e3 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/rules.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/rules.rs @@ -82,7 +82,7 @@ impl Violation for UnusedLambdaArgument { /// Check a plain function for unused arguments. fn function( - argumentable: &Argumentable, + argumentable: Argumentable, args: &Arguments, values: &Scope, bindings: &Bindings, @@ -109,7 +109,7 @@ fn function( /// Check a method for unused arguments. fn method( - argumentable: &Argumentable, + argumentable: Argumentable, args: &Arguments, values: &Scope, bindings: &Bindings, @@ -136,7 +136,7 @@ fn method( } fn call<'a>( - argumentable: &Argumentable, + argumentable: Argumentable, args: impl Iterator, values: &Scope, bindings: &Bindings, @@ -193,7 +193,7 @@ pub fn unused_arguments( && !visibility::is_overload(&checker.ctx, decorator_list) { function( - &Argumentable::Function, + Argumentable::Function, args, scope, bindings, @@ -222,7 +222,7 @@ pub fn unused_arguments( && !visibility::is_overload(&checker.ctx, decorator_list) { method( - &Argumentable::Method, + Argumentable::Method, args, scope, bindings, @@ -251,7 +251,7 @@ pub fn unused_arguments( && !visibility::is_overload(&checker.ctx, decorator_list) { method( - &Argumentable::ClassMethod, + Argumentable::ClassMethod, args, scope, bindings, @@ -280,7 +280,7 @@ pub fn unused_arguments( && !visibility::is_overload(&checker.ctx, decorator_list) { function( - &Argumentable::StaticMethod, + Argumentable::StaticMethod, args, scope, bindings, @@ -303,7 +303,7 @@ pub fn unused_arguments( .enabled(Argumentable::Lambda.rule_code()) { function( - &Argumentable::Lambda, + Argumentable::Lambda, args, scope, bindings, diff --git a/crates/ruff/src/rules/flake8_unused_arguments/types.rs b/crates/ruff/src/rules/flake8_unused_arguments/types.rs index 05bd2535cf75c1..b4a8c6d871026d 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/types.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/types.rs @@ -5,6 +5,7 @@ use crate::registry::Rule; use super::rules; /// An AST node that can contain arguments. +#[derive(Copy, Clone)] pub enum Argumentable { Function, Method, @@ -14,7 +15,7 @@ pub enum Argumentable { } impl Argumentable { - pub fn check_for(&self, name: String) -> DiagnosticKind { + pub fn check_for(self, name: String) -> DiagnosticKind { match self { Self::Function => rules::UnusedFunctionArgument { 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 { Self::Function => Rule::UnusedFunctionArgument, Self::Method => Rule::UnusedMethodArgument, diff --git a/crates/ruff/src/rules/isort/categorize.rs b/crates/ruff/src/rules/isort/categorize.rs index 602c4e9d9f93d6..8058871a09950b 100644 --- a/crates/ruff/src/rules/isort/categorize.rs +++ b/crates/ruff/src/rules/isort/categorize.rs @@ -20,6 +20,7 @@ use super::types::{ImportBlock, Importable}; Ord, PartialEq, Eq, + Copy, Clone, Serialize, Deserialize, diff --git a/crates/ruff/src/rules/isort/format.rs b/crates/ruff/src/rules/isort/format.rs index d7fd45424d3c6c..da06c1b818d521 100644 --- a/crates/ruff/src/rules/isort/format.rs +++ b/crates/ruff/src/rules/isort/format.rs @@ -15,11 +15,11 @@ pub fn format_import( ) -> String { let mut output = String::with_capacity(CAPACITY); if !is_first && !comments.atop.is_empty() { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } for comment in &comments.atop { output.push_str(comment); - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } if let Some(asname) = alias.asname { output.push_str("import "); @@ -34,7 +34,7 @@ pub fn format_import( output.push_str(" "); output.push_str(comment); } - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); output } @@ -94,11 +94,11 @@ fn format_single_line( let mut line_width = 0; if !is_first && !comments.atop.is_empty() { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } for comment in &comments.atop { output.push_str(comment); - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } let module_name = import_from.module_name(); @@ -137,7 +137,7 @@ fn format_single_line( line_width += 2 + comment.width(); } - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); (output, line_width) } @@ -153,11 +153,11 @@ fn format_multi_line( let mut output = String::with_capacity(CAPACITY); if !is_first && !comments.atop.is_empty() { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } for comment in &comments.atop { output.push_str(comment); - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } output.push_str("from "); @@ -169,13 +169,13 @@ fn format_multi_line( output.push(' '); output.push_str(comment); } - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); for (AliasData { name, asname }, comments) in aliases { for comment in &comments.atop { output.push_str(stylist.indentation()); output.push_str(comment); - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } output.push_str(stylist.indentation()); if let Some(asname) = asname { @@ -192,11 +192,11 @@ fn format_multi_line( output.push(' '); output.push_str(comment); } - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } output.push(')'); - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); output } diff --git a/crates/ruff/src/rules/isort/mod.rs b/crates/ruff/src/rules/isort/mod.rs index 71fa5926b39dbc..abc50e5f2ee38f 100644 --- a/crates/ruff/src/rules/isort/mod.rs +++ b/crates/ruff/src/rules/isort/mod.rs @@ -172,7 +172,7 @@ pub fn format_imports( if !block_output.is_empty() && !output.is_empty() { // If we are about to output something, and had already // output a block, separate them. - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } output.push_str(block_output.as_str()); } @@ -182,20 +182,20 @@ pub fn format_imports( Some(Trailer::Sibling) => { if lines_after_imports >= 0 { for _ in 0..lines_after_imports { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } } else { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } } Some(Trailer::FunctionDef | Trailer::ClassDef) => { if lines_after_imports >= 0 { for _ in 0..lines_after_imports { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } } 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; pending_lines_before = false; } else if pending_lines_before { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); pending_lines_before = false; } @@ -301,7 +301,7 @@ fn format_import_block( // Add a blank lines between direct and from imports if lines_between_types > 0 && has_direct_import && !lines_inserted { for _ in 0..lines_between_types { - output.push_str(stylist.line_ending()); + output.push_str(&stylist.line_ending()); } lines_inserted = true; diff --git a/crates/ruff/src/rules/isort/sorting.rs b/crates/ruff/src/rules/isort/sorting.rs index 8e41e54a628100..c24d0b4f5980e3 100644 --- a/crates/ruff/src/rules/isort/sorting.rs +++ b/crates/ruff/src/rules/isort/sorting.rs @@ -10,7 +10,7 @@ use super::settings::RelativeImportsOrder; use super::types::EitherImport::{Import, ImportFrom}; use super::types::{AliasData, EitherImport, ImportFromData}; -#[derive(PartialOrd, Ord, PartialEq, Eq)] +#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone)] pub enum Prefix { Constants, Classes, diff --git a/crates/ruff/src/rules/isort/track.rs b/crates/ruff/src/rules/isort/track.rs index 4e666d088a70b7..f0aeaaa2b76f08 100644 --- a/crates/ruff/src/rules/isort/track.rs +++ b/crates/ruff/src/rules/isort/track.rs @@ -14,7 +14,7 @@ use crate::directives::IsortDirectives; use super::helpers; -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub enum Trailer { Sibling, ClassDef, diff --git a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs index 6f4c3a3a20aaae..d65499570eceaf 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs @@ -11,7 +11,7 @@ use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::pycodestyle::helpers::compare; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum EqCmpop { Eq, NotEq, diff --git a/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs b/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs index 3b56ccb4e8a790..a0852a21dfd1d5 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs @@ -93,11 +93,7 @@ impl Violation for UndocumentedPublicInit { } /// D100, D101, D102, D103, D104, D105, D106, D107 -pub fn not_missing( - checker: &mut Checker, - definition: &Definition, - visibility: &Visibility, -) -> bool { +pub fn not_missing(checker: &mut Checker, definition: &Definition, visibility: Visibility) -> bool { if matches!(visibility, Visibility::Private) { return true; } diff --git a/crates/ruff/src/rules/pydocstyle/rules/sections.rs b/crates/ruff/src/rules/pydocstyle/rules/sections.rs index 49c8bbc11ebcac..19c591fdbfa2f5 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/sections.rs @@ -280,12 +280,12 @@ pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option match convention { Some(Convention::Google) => { - for context in §ion_contexts(&lines, &SectionStyle::Google) { + for context in §ion_contexts(&lines, SectionStyle::Google) { google_section(checker, docstring, context); } } Some(Convention::Numpy) => { - for context in §ion_contexts(&lines, &SectionStyle::Numpy) { + for context in §ion_contexts(&lines, SectionStyle::Numpy) { 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 // convention. - let numpy_sections = section_contexts(&lines, &SectionStyle::Numpy); + let numpy_sections = section_contexts(&lines, SectionStyle::Numpy); if numpy_sections.iter().any(|context| { matches!( 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. - let google_sections = section_contexts(&lines, &SectionStyle::Google); + let google_sections = section_contexts(&lines, SectionStyle::Google); if google_sections .iter() .any(|context| matches!(context.kind, SectionKind::Arguments | SectionKind::Args)) diff --git a/crates/ruff/src/rules/pyflakes/fixes.rs b/crates/ruff/src/rules/pyflakes/fixes.rs index e1aefbcdb7610b..6a3603920dcc1a 100644 --- a/crates/ruff/src/rules/pyflakes/fixes.rs +++ b/crates/ruff/src/rules/pyflakes/fixes.rs @@ -34,7 +34,7 @@ pub fn remove_unused_format_arguments_from_dict( }); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..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))); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -170,7 +170,7 @@ pub fn remove_unused_positional_arguments_from_format_call( } let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/pyflakes/rules/imports.rs b/crates/ruff/src/rules/pyflakes/rules/imports.rs index 77c56b5832b307..339d710b9ad3cc 100644 --- a/crates/ruff/src/rules/pyflakes/rules/imports.rs +++ b/crates/ruff/src/rules/pyflakes/rules/imports.rs @@ -9,7 +9,7 @@ use ruff_python_stdlib::future::ALL_FEATURE_NAMES; use crate::checkers::ast::Checker; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum UnusedImportContext { ExceptHandler, Init, diff --git a/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs b/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs index 228a21dbc2f31e..9012ce76b77544 100644 --- a/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs +++ b/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs @@ -12,7 +12,7 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; use crate::registry::AsRule; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum IsCmpop { Is, IsNot, diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs index cc261a5df02afd..172a26eaa9b5fd 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs @@ -183,6 +183,7 @@ where unreachable!("No token after matched"); } +#[derive(Copy, Clone)] enum DeletionKind { Whole, Partial, diff --git a/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs b/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs index eda1297eff0d01..2762518a166772 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs @@ -30,7 +30,7 @@ impl Violation for BadStrStripCall { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum StripKind { Strip, LStrip, @@ -59,14 +59,14 @@ impl fmt::Display for StripKind { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum RemovalKind { RemovePrefix, RemoveSuffix, } impl RemovalKind { - pub fn for_strip(s: &StripKind) -> Option { + pub fn for_strip(s: StripKind) -> Option { match s { StripKind::Strip => None, 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) { let removal = if checker.settings.target_version >= PythonVersion::Py39 { - RemovalKind::for_strip(&strip) + RemovalKind::for_strip(strip) } else { None }; diff --git a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs index 20ef7bd0fb8112..8a9650aaad0fa7 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs @@ -38,7 +38,7 @@ impl Violation for BadStringFormatType { } } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum DataType { String, Integer, @@ -87,7 +87,7 @@ impl From<&Expr> for DataType { } impl DataType { - fn is_compatible_with(&self, format: &FormatType) -> bool { + fn is_compatible_with(self, format: FormatType) -> bool { match self { DataType::String => matches!( format, @@ -119,7 +119,7 @@ impl DataType { } } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum FormatType { Repr, String, @@ -161,7 +161,7 @@ fn collect_specs(formats: &[CFormatStrOrBytes]) -> Vec<&CFormatSpec> { fn equivalent(format: &CFormatSpec, value: &Expr) -> bool { let constant: DataType = value.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. diff --git a/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs b/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs index a343356b961f32..110a2927ef9a7b 100644 --- a/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs +++ b/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs @@ -10,7 +10,7 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum ViolationsCmpop { Eq, NotEq, diff --git a/crates/ruff/src/rules/pyupgrade/fixes.rs b/crates/ruff/src/rules/pyupgrade/fixes.rs index 2be0446fa23c0c..74522d8b0680d6 100644 --- a/crates/ruff/src/rules/pyupgrade/fixes.rs +++ b/crates/ruff/src/rules/pyupgrade/fixes.rs @@ -35,7 +35,7 @@ pub fn adjust_indentation( indented_block.indent = Some(indentation); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..Default::default() }; @@ -71,7 +71,7 @@ pub fn remove_super_arguments(locator: &Locator, stylist: &Stylist, expr: &Expr) body.whitespace_after_func = ParenthesizableWhitespace::default(); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs index 6575bd2f7cb04a..1f5c7341a50edc 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs @@ -17,7 +17,7 @@ use crate::checkers::ast::Checker; use crate::cst::matchers::{match_import, match_import_from, match_module}; use crate::registry::{AsRule, Rule}; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum MockReference { Import, Attribute, @@ -99,7 +99,7 @@ fn format_mocks(aliases: Vec>, indent: &str, stylist: &Stylist) - match alias { None => { if !content.is_empty() { - content.push_str(stylist.line_ending()); + content.push_str(&stylist.line_ending()); content.push_str(indent); } content.push_str("from unittest import mock"); @@ -107,7 +107,7 @@ fn format_mocks(aliases: Vec>, indent: &str, stylist: &Stylist) - Some(as_name) => { if let AssignTargetExpression::Name(name) = as_name.name { if !content.is_empty() { - content.push_str(stylist.line_ending()); + content.push_str(&stylist.line_ending()); content.push_str(indent); } content.push_str("from unittest import mock as "); @@ -139,14 +139,14 @@ fn format_import( import.names = clean_aliases; let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; tree.codegen(&mut state); 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(&format_mocks(mock_aliases, indent, stylist)); content @@ -189,7 +189,7 @@ fn format_import_from( rpar: vec![], }))); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -226,7 +226,7 @@ fn format_import_from( }))); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -234,7 +234,7 @@ fn format_import_from( let mut content = state.to_string(); if !mock_aliases.is_empty() { - content.push_str(stylist.line_ending()); + content.push_str(&stylist.line_ending()); content.push_str(indent); content.push_str(&format_mocks(mock_aliases, indent, stylist)); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs index 9d40a1074f9feb..314d816abf0c0a 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs @@ -101,7 +101,7 @@ fn generate_call( }; let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; @@ -111,7 +111,7 @@ fn generate_call( call.func = Box::new(match_expression(&cleaned)?); let mut state = CodegenState { - default_newline: stylist.line_ending(), + default_newline: &stylist.line_ending(), default_indent: stylist.indentation(), ..CodegenState::default() }; diff --git a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs index c28afc0d44dc73..ab121ac7ec71cc 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs @@ -10,7 +10,7 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; use crate::registry::AsRule; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum LiteralType { Str, Bytes, diff --git a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs index 581187e81974cf..21e28724dd32cf 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs @@ -44,6 +44,7 @@ impl AlwaysAutofixableViolation for RedundantOpenModes { const OPEN_FUNC_NAME: &str = "open"; const MODE_KEYWORD_ARGUMENT: &str = "mode"; +#[derive(Copy, Clone)] enum OpenMode { U, Ur, @@ -72,15 +73,15 @@ impl FromStr for OpenMode { } impl OpenMode { - fn replacement_value(&self) -> Option { - match *self { + fn replacement_value(self) -> Option<&'static str> { + match self { Self::U => None, Self::Ur => None, - Self::Ub => Some(String::from("\"rb\"")), - Self::RUb => Some(String::from("\"rb\"")), + Self::Ub => Some("\"rb\""), + Self::RUb => Some("\"rb\""), Self::R => 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) { fn create_check( expr: &Expr, mode_param: &Expr, - replacement_value: Option, + replacement_value: Option<&str>, locator: &Locator, patch: bool, ) -> Diagnostic { let mut diagnostic = Diagnostic::new( RedundantOpenModes { - replacement: replacement_value.clone(), + replacement: replacement_value.map(ToString::to_string), }, Range::from(expr), ); if patch { if let Some(content) = replacement_value { diagnostic.set_fix(Edit::replacement( - content, + content.to_string(), mode_param.location, mode_param.end_location.unwrap(), )); diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs index b2f54b544b0aa5..3b7af8f0b08c4a 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs @@ -123,7 +123,7 @@ pub fn unnecessary_builtin_import( ) { Ok(fix) => { if fix.content.is_empty() || fix.content == "pass" { - checker.deletions.insert(defined_by.clone()); + checker.deletions.insert(*defined_by); } diagnostic.set_fix(fix); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs index 9a0e97ae6acb2f..6bea7e6d0524ad 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs @@ -103,7 +103,7 @@ pub fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, names: &[Lo ) { Ok(fix) => { if fix.content.is_empty() || fix.content == "pass" { - checker.deletions.insert(defined_by.clone()); + checker.deletions.insert(*defined_by); } diagnostic.set_fix(fix); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs index 87d509e736ffac..cecf1c387f1fce 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -74,6 +74,7 @@ fn any_arg_is_str(slice: &Expr) -> bool { } } +#[derive(Copy, Clone)] enum TypingMember { Union, Optional, diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs index 8aaac3b5d23e94..0eb4a40990ae8c 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs @@ -10,7 +10,7 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; use crate::registry::AsRule; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum CallKind { Isinstance, Issubclass, diff --git a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs index 5dabb77ed09acc..172333a8269bf7 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs @@ -62,7 +62,7 @@ pub fn useless_metaclass_type(checker: &mut Checker, stmt: &Stmt, value: &Expr, ) { Ok(fix) => { if fix.content.is_empty() || fix.content == "pass" { - checker.deletions.insert(defined_by.clone()); + checker.deletions.insert(*defined_by); } diagnostic.set_fix(fix); } diff --git a/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs b/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs index 040a0be246dff0..90a9bb9a56d7d7 100644 --- a/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs +++ b/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs @@ -62,7 +62,7 @@ impl Violation for AsyncioDanglingTask { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Method { CreateTask, EnsureFuture, diff --git a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs index 697e956dcf3404..85f97a159e1857 100644 --- a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs +++ b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs @@ -49,7 +49,7 @@ fn make_splat_elts( new_elts } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum Kind { List, Tuple, diff --git a/crates/ruff_cli/src/lib.rs b/crates/ruff_cli/src/lib.rs index 9768a493cf05a3..f8bb63a49b6bba 100644 --- a/crates/ruff_cli/src/lib.rs +++ b/crates/ruff_cli/src/lib.rs @@ -23,6 +23,7 @@ mod panic; mod printer; mod resolve; +#[derive(Copy, Clone)] pub enum ExitStatus { /// Linting was successful and there were no linting errors. Success, diff --git a/crates/ruff_diagnostics/src/violation.rs b/crates/ruff_diagnostics/src/violation.rs index 016afc9c56ae05..e4bb9034ae6fbe 100644 --- a/crates/ruff_diagnostics/src/violation.rs +++ b/crates/ruff_diagnostics/src/violation.rs @@ -1,5 +1,6 @@ use std::fmt::{Debug, Display}; +#[derive(Copy, Clone)] pub enum AutofixKind { Sometimes, Always, diff --git a/crates/ruff_python_ast/src/branch_detection.rs b/crates/ruff_python_ast/src/branch_detection.rs index 71de63f32471ff..42850452d9777a 100644 --- a/crates/ruff_python_ast/src/branch_detection.rs +++ b/crates/ruff_python_ast/src/branch_detection.rs @@ -8,40 +8,39 @@ use crate::types::RefEquality; /// Return the common ancestor of `left` and `right` below `stop`, or `None`. fn common_ancestor<'a>( - left: &'a RefEquality<'a, Stmt>, - right: &'a RefEquality<'a, Stmt>, - stop: Option<&'a RefEquality<'a, Stmt>>, + left: RefEquality<'a, Stmt>, + right: RefEquality<'a, Stmt>, + stop: Option>, depths: &'a FxHashMap, usize>, child_to_parent: &'a FxHashMap, RefEquality<'a, Stmt>>, -) -> Option<&'a RefEquality<'a, Stmt>> { - if let Some(stop) = stop { - if left == stop || right == stop { - return None; - } +) -> Option> { + if Some(left) == stop || Some(right) == stop { + return None; } + if left == right { return Some(left); } - let left_depth = depths.get(left)?; - let right_depth = depths.get(right)?; + let left_depth = depths.get(&left)?; + let right_depth = depths.get(&right)?; match left_depth.cmp(right_depth) { Ordering::Less => common_ancestor( left, - child_to_parent.get(right)?, + *child_to_parent.get(&right)?, stop, depths, child_to_parent, ), Ordering::Equal => common_ancestor( - child_to_parent.get(left)?, - child_to_parent.get(right)?, + *child_to_parent.get(&left)?, + *child_to_parent.get(&right)?, stop, depths, child_to_parent, ), Ordering::Greater => common_ancestor( - child_to_parent.get(left)?, + *child_to_parent.get(&left)?, right, stop, depths, @@ -51,8 +50,8 @@ fn common_ancestor<'a>( } /// Return the alternative branches for a given node. -fn alternatives<'a>(stmt: &'a RefEquality<'a, Stmt>) -> Vec>> { - match &stmt.node { +fn alternatives(stmt: RefEquality) -> Vec>> { + match &stmt.as_ref().node { StmtKind::If { body, .. } => vec![body.iter().map(RefEquality).collect()], StmtKind::Try { body, @@ -78,22 +77,22 @@ fn alternatives<'a>(stmt: &'a RefEquality<'a, Stmt>) -> Vec( - stmt: &RefEquality<'a, Stmt>, + stmt: RefEquality<'a, Stmt>, ancestors: &[RefEquality<'a, Stmt>], - stop: &RefEquality<'a, Stmt>, + stop: RefEquality<'a, Stmt>, depths: &FxHashMap, usize>, child_to_parent: &FxHashMap, RefEquality<'a, Stmt>>, ) -> bool { 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 /// `try` statement. pub fn different_forks<'a>( - left: &RefEquality<'a, Stmt>, - right: &RefEquality<'a, Stmt>, + left: RefEquality<'a, Stmt>, + right: RefEquality<'a, Stmt>, depths: &FxHashMap, usize>, child_to_parent: &FxHashMap, RefEquality<'a, Stmt>>, ) -> bool { diff --git a/crates/ruff_python_ast/src/comparable.rs b/crates/ruff_python_ast/src/comparable.rs index e38a191b3aa036..3cb4fcee198772 100644 --- a/crates/ruff_python_ast/src/comparable.rs +++ b/crates/ruff_python_ast/src/comparable.rs @@ -9,7 +9,7 @@ use rustpython_parser::ast::{ use num_bigint::BigInt; -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum ComparableExprContext { Load, 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 { And, 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 { Add, 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 { Invert, 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 { Eq, NotEq, diff --git a/crates/ruff_python_ast/src/context.rs b/crates/ruff_python_ast/src/context.rs index bff83be6c13868..63030b9bdcdcec 100644 --- a/crates/ruff_python_ast/src/context.rs +++ b/crates/ruff_python_ast/src/context.rs @@ -206,13 +206,10 @@ impl<'a> Context<'a> { pub fn push_parent(&mut self, parent: &'a Stmt) { let num_existing = self.parents.len(); self.parents.push(RefEquality(parent)); - self.depths - .insert(self.parents[num_existing].clone(), num_existing); + self.depths.insert(self.parents[num_existing], num_existing); if num_existing > 0 { - self.child_to_parent.insert( - self.parents[num_existing].clone(), - self.parents[num_existing - 1].clone(), - ); + self.child_to_parent + .insert(self.parents[num_existing], self.parents[num_existing - 1]); } } diff --git a/crates/ruff_python_ast/src/function_type.rs b/crates/ruff_python_ast/src/function_type.rs index 79c80f4c327f88..9c3b88ffd50d01 100644 --- a/crates/ruff_python_ast/src/function_type.rs +++ b/crates/ruff_python_ast/src/function_type.rs @@ -7,6 +7,7 @@ use crate::scope::{Scope, ScopeKind}; const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"]; const METACLASS_BASES: [(&str, &str); 2] = [("", "type"), ("abc", "ABCMeta")]; +#[derive(Copy, Clone)] pub enum FunctionType { Function, Method, diff --git a/crates/ruff_python_ast/src/logging.rs b/crates/ruff_python_ast/src/logging.rs index 92693421de6164..262132967dbc42 100644 --- a/crates/ruff_python_ast/src/logging.rs +++ b/crates/ruff_python_ast/src/logging.rs @@ -1,3 +1,4 @@ +#[derive(Copy, Clone)] pub enum LoggingLevel { Debug, Critical, diff --git a/crates/ruff_python_ast/src/scope.rs b/crates/ruff_python_ast/src/scope.rs index 0e792a4b3406c8..b5b1fc14962b0c 100644 --- a/crates/ruff_python_ast/src/scope.rs +++ b/crates/ruff_python_ast/src/scope.rs @@ -215,8 +215,19 @@ impl ScopeStack { pub fn iter(&self) -> std::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 { fn default() -> Self { Self(vec![ScopeId::global()]) diff --git a/crates/ruff_python_ast/src/source_code/generator.rs b/crates/ruff_python_ast/src/source_code/generator.rs index bae7dbbb3db4a3..98c6b35fa1f8a0 100644 --- a/crates/ruff_python_ast/src/source_code/generator.rs +++ b/crates/ruff_python_ast/src/source_code/generator.rs @@ -65,7 +65,7 @@ pub struct Generator<'a> { /// The quote style to use for string literals. quote: Quote, /// The line ending to use. - line_ending: &'a LineEnding, + line_ending: LineEnding, buffer: String, indent_depth: usize, num_newlines: usize, @@ -87,7 +87,7 @@ impl<'a> From<&'a Stylist<'a>> for 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 { // Style preferences. indent, @@ -128,7 +128,7 @@ impl<'a> Generator<'a> { fn p(&mut self, s: &str) { if self.num_newlines > 0 { for _ in 0..self.num_newlines { - self.buffer += self.line_ending; + self.buffer += &self.line_ending; } self.num_newlines = 0; } @@ -1266,7 +1266,7 @@ mod tests { let line_ending = LineEnding::default(); let program = parser::parse_program(contents, "").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.generate() } @@ -1274,7 +1274,7 @@ mod tests { fn round_trip_with( indentation: &Indentation, quote: Quote, - line_ending: &LineEnding, + line_ending: LineEnding, contents: &str, ) -> String { let program = parser::parse_program(contents, "").unwrap(); @@ -1449,7 +1449,7 @@ if True: round_trip_with( &Indentation::default(), Quote::Double, - &LineEnding::default(), + LineEnding::default(), r#""hello""# ), r#""hello""# @@ -1458,7 +1458,7 @@ if True: round_trip_with( &Indentation::default(), Quote::Single, - &LineEnding::default(), + LineEnding::default(), r#""hello""# ), r#"'hello'"# @@ -1467,7 +1467,7 @@ if True: round_trip_with( &Indentation::default(), Quote::Double, - &LineEnding::default(), + LineEnding::default(), r#"'hello'"# ), r#""hello""# @@ -1476,7 +1476,7 @@ if True: round_trip_with( &Indentation::default(), Quote::Single, - &LineEnding::default(), + LineEnding::default(), r#"'hello'"# ), r#"'hello'"# @@ -1489,7 +1489,7 @@ if True: round_trip_with( &Indentation::new(" ".to_string()), Quote::default(), - &LineEnding::default(), + LineEnding::default(), r#" if True: pass @@ -1507,7 +1507,7 @@ if True: round_trip_with( &Indentation::new(" ".to_string()), Quote::default(), - &LineEnding::default(), + LineEnding::default(), r#" if True: pass @@ -1525,7 +1525,7 @@ if True: round_trip_with( &Indentation::new("\t".to_string()), Quote::default(), - &LineEnding::default(), + LineEnding::default(), r#" if True: pass @@ -1547,7 +1547,7 @@ if True: round_trip_with( &Indentation::default(), Quote::default(), - &LineEnding::Lf, + LineEnding::Lf, "if True:\n print(42)", ), "if True:\n print(42)", @@ -1557,7 +1557,7 @@ if True: round_trip_with( &Indentation::default(), Quote::default(), - &LineEnding::CrLf, + LineEnding::CrLf, "if True:\n print(42)", ), "if True:\r\n print(42)", @@ -1567,7 +1567,7 @@ if True: round_trip_with( &Indentation::default(), Quote::default(), - &LineEnding::Cr, + LineEnding::Cr, "if True:\n print(42)", ), "if True:\r print(42)", diff --git a/crates/ruff_python_ast/src/source_code/stylist.rs b/crates/ruff_python_ast/src/source_code/stylist.rs index 6cfa212efc7af2..bef99db2bd634d 100644 --- a/crates/ruff_python_ast/src/source_code/stylist.rs +++ b/crates/ruff_python_ast/src/source_code/stylist.rs @@ -56,8 +56,9 @@ impl<'a> Stylist<'a> { }) } - pub fn line_ending(&'a self) -> &'a LineEnding { - self.line_ending + pub fn line_ending(&'a self) -> LineEnding { + *self + .line_ending .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. /// See -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum LineEnding { Lf, Cr, diff --git a/crates/ruff_python_ast/src/types.rs b/crates/ruff_python_ast/src/types.rs index 19c020d7d7c7b8..de5fb23a74896c 100644 --- a/crates/ruff_python_ast/src/types.rs +++ b/crates/ruff_python_ast/src/types.rs @@ -35,9 +35,23 @@ impl From<&Box>> for Range { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug)] pub struct RefEquality<'a, T>(pub &'a T); +impl<'a, T> RefEquality<'a, T> { + pub fn as_ref(&self) -> &'a 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> { fn hash(&self, state: &mut H) where diff --git a/crates/ruff_python_ast/src/typing.rs b/crates/ruff_python_ast/src/typing.rs index 11db4d2e46dfa8..3fce6026704e32 100644 --- a/crates/ruff_python_ast/src/typing.rs +++ b/crates/ruff_python_ast/src/typing.rs @@ -10,6 +10,7 @@ use crate::source_code::Locator; use crate::str; use crate::types::Range; +#[derive(Copy, Clone)] pub enum Callable { Cast, NewType, @@ -19,6 +20,7 @@ pub enum Callable { MypyExtension, } +#[derive(Copy, Clone)] pub enum SubscriptKind { AnnotatedSubscript, 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 { /// The annotation is defined as part a simple string literal, /// e.g. `x: "List[int]" = []`. Annotations within simple literals diff --git a/crates/ruff_python_ast/src/visibility.rs b/crates/ruff_python_ast/src/visibility.rs index 7bf400132a5837..7ba1f18d9feb66 100644 --- a/crates/ruff_python_ast/src/visibility.rs +++ b/crates/ruff_python_ast/src/visibility.rs @@ -6,20 +6,20 @@ use crate::context::Context; use crate::helpers::{collect_call_path, map_callable}; use crate::types::CallPath; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub enum Modifier { Module, Class, Function, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub enum Visibility { Public, Private, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct VisibleScope { pub modifier: Modifier, pub visibility: Visibility,