mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-22 20:45:11 +00:00
Rename Arguments
to Parameters
in the AST (#6253)
## Summary This PR renames a few AST nodes for clarity: - `Arguments` is now `Parameters` - `Arg` is now `Parameter` - `ArgWithDefault` is now `ParameterWithDefault` For now, the attribute names that reference `Parameters` directly are changed (e.g., on `StmtFunctionDef`), but the attributes on `Parameters` itself are not (e.g., `vararg`). We may revisit that decision in the future. For context, the AST node formerly known as `Arguments` is used in function definitions. Formally (outside of the Python context), "arguments" typically refers to "the values passed to a function", while "parameters" typically refers to "the variables used in a function definition". E.g., if you Google "arguments vs parameters", you'll get some explanation like: > A parameter is a variable in a function definition. It is a placeholder and hence does not have a concrete value. An argument is a value passed during function invocation. We're thus deviating from Python's nomenclature in favor of a scheme that we find to be more precise.
This commit is contained in:
parent
a82eb9544c
commit
adc8bb7821
102 changed files with 2585 additions and 2529 deletions
|
@ -1,8 +1,8 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use ruff_python_ast::{
|
||||
self as ast, Arguments, Comprehension, Expr, ExprAttribute, ExprBinOp, ExprIfExp, ExprSlice,
|
||||
ExprStarred, MatchCase, Ranged,
|
||||
self as ast, Comprehension, Expr, ExprAttribute, ExprBinOp, ExprIfExp, ExprSlice, ExprStarred,
|
||||
MatchCase, Parameters, Ranged,
|
||||
};
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
|
@ -15,7 +15,7 @@ use ruff_source_file::{Locator, UniversalNewlines};
|
|||
|
||||
use crate::comments::visitor::{CommentPlacement, DecoratedComment};
|
||||
use crate::expression::expr_slice::{assign_comment_in_slice, ExprSliceCommentSection};
|
||||
use crate::other::arguments::{
|
||||
use crate::other::parameters::{
|
||||
assign_argument_separator_comment_placement, find_argument_separators,
|
||||
};
|
||||
|
||||
|
@ -44,8 +44,8 @@ pub(super) fn place_comment<'a>(
|
|||
// Change comment placement depending on the node type. These can be seen as node-specific
|
||||
// fixups.
|
||||
match comment.enclosing_node() {
|
||||
AnyNodeRef::Arguments(arguments) => {
|
||||
handle_arguments_separator_comment(comment, arguments, locator)
|
||||
AnyNodeRef::Parameters(arguments) => {
|
||||
handle_parameters_separator_comment(comment, arguments, locator)
|
||||
}
|
||||
AnyNodeRef::Comprehension(comprehension) => {
|
||||
handle_comprehension_comment(comment, comprehension, locator)
|
||||
|
@ -559,16 +559,16 @@ fn handle_own_line_comment_after_branch<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Attaches comments for the positional only arguments separator `/` or the keywords only arguments
|
||||
/// separator `*` as dangling comments to the enclosing [`Arguments`] node.
|
||||
/// Attaches comments for the positional-only parameters separator `/` or the keywords-only
|
||||
/// parameters separator `*` as dangling comments to the enclosing [`Parameters`] node.
|
||||
///
|
||||
/// See [`assign_argument_separator_comment_placement`]
|
||||
fn handle_arguments_separator_comment<'a>(
|
||||
fn handle_parameters_separator_comment<'a>(
|
||||
comment: DecoratedComment<'a>,
|
||||
arguments: &Arguments,
|
||||
parameters: &Parameters,
|
||||
locator: &Locator,
|
||||
) -> CommentPlacement<'a> {
|
||||
let (slash, star) = find_argument_separators(locator.contents(), arguments);
|
||||
let (slash, star) = find_argument_separators(locator.contents(), parameters);
|
||||
let comment_range = comment.slice().range();
|
||||
let placement = assign_argument_separator_comment_placement(
|
||||
slash.as_ref(),
|
||||
|
@ -832,11 +832,11 @@ fn handle_leading_function_with_decorators_comment(comment: DecoratedComment) ->
|
|||
.preceding_node()
|
||||
.is_some_and(|node| node.is_decorator());
|
||||
|
||||
let is_following_arguments = comment
|
||||
let is_following_parameters = comment
|
||||
.following_node()
|
||||
.is_some_and(|node| node.is_arguments());
|
||||
.is_some_and(|node| node.is_parameters());
|
||||
|
||||
if comment.line_position().is_own_line() && is_preceding_decorator && is_following_arguments {
|
||||
if comment.line_position().is_own_line() && is_preceding_decorator && is_following_parameters {
|
||||
CommentPlacement::dangling(comment.enclosing_node(), comment)
|
||||
} else {
|
||||
CommentPlacement::Default(comment)
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: Arguments,
|
||||
kind: Parameters,
|
||||
range: 9..39,
|
||||
source: `(⏎`,
|
||||
}: {
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: Arguments,
|
||||
kind: Parameters,
|
||||
range: 9..96,
|
||||
source: `(a=10,/, # trailing positio...t comment.⏎`,
|
||||
}: {
|
||||
|
@ -19,7 +19,7 @@ expression: comments.debug(test_case.source_code)
|
|||
"trailing": [],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 90..94,
|
||||
source: `b=20`,
|
||||
}: {
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: Arguments,
|
||||
kind: Parameters,
|
||||
range: 9..179,
|
||||
source: `(⏎`,
|
||||
}: {
|
||||
|
@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code)
|
|||
"trailing": [],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 15..19,
|
||||
source: `a=10`,
|
||||
}: {
|
||||
|
@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code)
|
|||
],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 173..177,
|
||||
source: `b=20`,
|
||||
}: {
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: Arguments,
|
||||
kind: Parameters,
|
||||
range: 9..170,
|
||||
source: `(⏎`,
|
||||
}: {
|
||||
|
@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code)
|
|||
"trailing": [],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 15..16,
|
||||
source: `a`,
|
||||
}: {
|
||||
|
@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code)
|
|||
],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 166..167,
|
||||
source: `b`,
|
||||
}: {
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: Arguments,
|
||||
kind: Parameters,
|
||||
range: 9..166,
|
||||
source: `(⏎`,
|
||||
}: {
|
||||
|
@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code)
|
|||
"trailing": [],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 15..16,
|
||||
source: `a`,
|
||||
}: {
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: Arguments,
|
||||
kind: Parameters,
|
||||
range: 9..170,
|
||||
source: `(⏎`,
|
||||
}: {
|
||||
|
@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code)
|
|||
"trailing": [],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 15..16,
|
||||
source: `a`,
|
||||
}: {
|
||||
|
@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code)
|
|||
],
|
||||
},
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 166..167,
|
||||
source: `b`,
|
||||
}: {
|
||||
|
|
|
@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code)
|
|||
---
|
||||
{
|
||||
Node {
|
||||
kind: ArgWithDefault,
|
||||
kind: ParameterWithDefault,
|
||||
range: 15..16,
|
||||
source: `a`,
|
||||
}: {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::iter::Peekable;
|
||||
|
||||
use ruff_python_ast::{
|
||||
Alias, Arg, ArgWithDefault, Arguments, Comprehension, Decorator, ElifElseClause, ExceptHandler,
|
||||
Expr, Keyword, MatchCase, Mod, Pattern, Ranged, Stmt, TypeParam, WithItem,
|
||||
Alias, Comprehension, Decorator, ElifElseClause, ExceptHandler, Expr, Keyword, MatchCase, Mod,
|
||||
Parameter, ParameterWithDefault, Parameters, Pattern, Ranged, Stmt, TypeParam, WithItem,
|
||||
};
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
|
@ -229,25 +229,25 @@ impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> {
|
|||
self.finish_node(format_spec);
|
||||
}
|
||||
|
||||
fn visit_arguments(&mut self, arguments: &'ast Arguments) {
|
||||
if self.start_node(arguments).is_traverse() {
|
||||
walk_arguments(self, arguments);
|
||||
fn visit_parameters(&mut self, parameters: &'ast Parameters) {
|
||||
if self.start_node(parameters).is_traverse() {
|
||||
walk_parameters(self, parameters);
|
||||
}
|
||||
self.finish_node(arguments);
|
||||
self.finish_node(parameters);
|
||||
}
|
||||
|
||||
fn visit_arg(&mut self, arg: &'ast Arg) {
|
||||
fn visit_parameter(&mut self, arg: &'ast Parameter) {
|
||||
if self.start_node(arg).is_traverse() {
|
||||
walk_arg(self, arg);
|
||||
walk_parameter(self, arg);
|
||||
}
|
||||
self.finish_node(arg);
|
||||
}
|
||||
|
||||
fn visit_arg_with_default(&mut self, arg_with_default: &'ast ArgWithDefault) {
|
||||
if self.start_node(arg_with_default).is_traverse() {
|
||||
walk_arg_with_default(self, arg_with_default);
|
||||
fn visit_parameter_with_default(&mut self, parameter_with_default: &'ast ParameterWithDefault) {
|
||||
if self.start_node(parameter_with_default).is_traverse() {
|
||||
walk_parameter_with_default(self, parameter_with_default);
|
||||
}
|
||||
self.finish_node(arg_with_default);
|
||||
self.finish_node(parameter_with_default);
|
||||
}
|
||||
|
||||
fn visit_keyword(&mut self, keyword: &'ast Keyword) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::comments::dangling_node_comments;
|
||||
use crate::context::PyFormatContext;
|
||||
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
||||
use crate::other::arguments::ArgumentsParentheses;
|
||||
use crate::other::parameters::ParametersParentheses;
|
||||
use crate::AsFormat;
|
||||
use crate::{FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::prelude::{space, text};
|
||||
|
@ -16,18 +16,20 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
|
|||
fn fmt_fields(&self, item: &ExprLambda, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let ExprLambda {
|
||||
range: _,
|
||||
args,
|
||||
parameters,
|
||||
body,
|
||||
} = item;
|
||||
|
||||
write!(f, [text("lambda")])?;
|
||||
|
||||
if !args.args.is_empty() {
|
||||
if !parameters.args.is_empty() {
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
space(),
|
||||
args.format().with_options(ArgumentsParentheses::Never),
|
||||
parameters
|
||||
.format()
|
||||
.with_options(ParametersParentheses::Never),
|
||||
]
|
||||
)?;
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
|
|||
// lambda # Dangling
|
||||
// : 1
|
||||
// )
|
||||
dangling_node_comments(args.as_ref())
|
||||
dangling_node_comments(parameters.as_ref())
|
||||
]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2617,95 +2617,108 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Comprehension {
|
|||
}
|
||||
}
|
||||
|
||||
impl FormatRule<ast::Arguments, PyFormatContext<'_>> for crate::other::arguments::FormatArguments {
|
||||
#[inline]
|
||||
fn fmt(
|
||||
&self,
|
||||
node: &ast::Arguments,
|
||||
f: &mut Formatter<PyFormatContext<'_>>,
|
||||
) -> FormatResult<()> {
|
||||
FormatNodeRule::<ast::Arguments>::fmt(self, node, f)
|
||||
}
|
||||
}
|
||||
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::Arguments {
|
||||
type Format<'a> = FormatRefWithRule<
|
||||
'a,
|
||||
ast::Arguments,
|
||||
crate::other::arguments::FormatArguments,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn format(&self) -> Self::Format<'_> {
|
||||
FormatRefWithRule::new(self, crate::other::arguments::FormatArguments::default())
|
||||
}
|
||||
}
|
||||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Arguments {
|
||||
type Format = FormatOwnedWithRule<
|
||||
ast::Arguments,
|
||||
crate::other::arguments::FormatArguments,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn into_format(self) -> Self::Format {
|
||||
FormatOwnedWithRule::new(self, crate::other::arguments::FormatArguments::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl FormatRule<ast::Arg, PyFormatContext<'_>> for crate::other::arg::FormatArg {
|
||||
#[inline]
|
||||
fn fmt(&self, node: &ast::Arg, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||
FormatNodeRule::<ast::Arg>::fmt(self, node, f)
|
||||
}
|
||||
}
|
||||
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::Arg {
|
||||
type Format<'a> =
|
||||
FormatRefWithRule<'a, ast::Arg, crate::other::arg::FormatArg, PyFormatContext<'ast>>;
|
||||
fn format(&self) -> Self::Format<'_> {
|
||||
FormatRefWithRule::new(self, crate::other::arg::FormatArg::default())
|
||||
}
|
||||
}
|
||||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Arg {
|
||||
type Format =
|
||||
FormatOwnedWithRule<ast::Arg, crate::other::arg::FormatArg, PyFormatContext<'ast>>;
|
||||
fn into_format(self) -> Self::Format {
|
||||
FormatOwnedWithRule::new(self, crate::other::arg::FormatArg::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl FormatRule<ast::ArgWithDefault, PyFormatContext<'_>>
|
||||
for crate::other::arg_with_default::FormatArgWithDefault
|
||||
impl FormatRule<ast::Parameters, PyFormatContext<'_>>
|
||||
for crate::other::parameters::FormatParameters
|
||||
{
|
||||
#[inline]
|
||||
fn fmt(
|
||||
&self,
|
||||
node: &ast::ArgWithDefault,
|
||||
node: &ast::Parameters,
|
||||
f: &mut Formatter<PyFormatContext<'_>>,
|
||||
) -> FormatResult<()> {
|
||||
FormatNodeRule::<ast::ArgWithDefault>::fmt(self, node, f)
|
||||
FormatNodeRule::<ast::Parameters>::fmt(self, node, f)
|
||||
}
|
||||
}
|
||||
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::ArgWithDefault {
|
||||
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::Parameters {
|
||||
type Format<'a> = FormatRefWithRule<
|
||||
'a,
|
||||
ast::ArgWithDefault,
|
||||
crate::other::arg_with_default::FormatArgWithDefault,
|
||||
ast::Parameters,
|
||||
crate::other::parameters::FormatParameters,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn format(&self) -> Self::Format<'_> {
|
||||
FormatRefWithRule::new(self, crate::other::parameters::FormatParameters::default())
|
||||
}
|
||||
}
|
||||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Parameters {
|
||||
type Format = FormatOwnedWithRule<
|
||||
ast::Parameters,
|
||||
crate::other::parameters::FormatParameters,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn into_format(self) -> Self::Format {
|
||||
FormatOwnedWithRule::new(self, crate::other::parameters::FormatParameters::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl FormatRule<ast::Parameter, PyFormatContext<'_>> for crate::other::parameter::FormatParameter {
|
||||
#[inline]
|
||||
fn fmt(
|
||||
&self,
|
||||
node: &ast::Parameter,
|
||||
f: &mut Formatter<PyFormatContext<'_>>,
|
||||
) -> FormatResult<()> {
|
||||
FormatNodeRule::<ast::Parameter>::fmt(self, node, f)
|
||||
}
|
||||
}
|
||||
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::Parameter {
|
||||
type Format<'a> = FormatRefWithRule<
|
||||
'a,
|
||||
ast::Parameter,
|
||||
crate::other::parameter::FormatParameter,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn format(&self) -> Self::Format<'_> {
|
||||
FormatRefWithRule::new(self, crate::other::parameter::FormatParameter::default())
|
||||
}
|
||||
}
|
||||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Parameter {
|
||||
type Format = FormatOwnedWithRule<
|
||||
ast::Parameter,
|
||||
crate::other::parameter::FormatParameter,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn into_format(self) -> Self::Format {
|
||||
FormatOwnedWithRule::new(self, crate::other::parameter::FormatParameter::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl FormatRule<ast::ParameterWithDefault, PyFormatContext<'_>>
|
||||
for crate::other::parameter_with_default::FormatParameterWithDefault
|
||||
{
|
||||
#[inline]
|
||||
fn fmt(
|
||||
&self,
|
||||
node: &ast::ParameterWithDefault,
|
||||
f: &mut Formatter<PyFormatContext<'_>>,
|
||||
) -> FormatResult<()> {
|
||||
FormatNodeRule::<ast::ParameterWithDefault>::fmt(self, node, f)
|
||||
}
|
||||
}
|
||||
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::ParameterWithDefault {
|
||||
type Format<'a> = FormatRefWithRule<
|
||||
'a,
|
||||
ast::ParameterWithDefault,
|
||||
crate::other::parameter_with_default::FormatParameterWithDefault,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn format(&self) -> Self::Format<'_> {
|
||||
FormatRefWithRule::new(
|
||||
self,
|
||||
crate::other::arg_with_default::FormatArgWithDefault::default(),
|
||||
crate::other::parameter_with_default::FormatParameterWithDefault::default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::ArgWithDefault {
|
||||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::ParameterWithDefault {
|
||||
type Format = FormatOwnedWithRule<
|
||||
ast::ArgWithDefault,
|
||||
crate::other::arg_with_default::FormatArgWithDefault,
|
||||
ast::ParameterWithDefault,
|
||||
crate::other::parameter_with_default::FormatParameterWithDefault,
|
||||
PyFormatContext<'ast>,
|
||||
>;
|
||||
fn into_format(self) -> Self::Format {
|
||||
FormatOwnedWithRule::new(
|
||||
self,
|
||||
crate::other::arg_with_default::FormatArgWithDefault::default(),
|
||||
crate::other::parameter_with_default::FormatParameterWithDefault::default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
pub(crate) mod alias;
|
||||
pub(crate) mod arg;
|
||||
pub(crate) mod arg_with_default;
|
||||
pub(crate) mod arguments;
|
||||
pub(crate) mod comprehension;
|
||||
pub(crate) mod decorator;
|
||||
pub(crate) mod elif_else_clause;
|
||||
|
@ -9,4 +6,7 @@ pub(crate) mod except_handler_except_handler;
|
|||
pub(crate) mod identifier;
|
||||
pub(crate) mod keyword;
|
||||
pub(crate) mod match_case;
|
||||
pub(crate) mod parameter;
|
||||
pub(crate) mod parameter_with_default;
|
||||
pub(crate) mod parameters;
|
||||
pub(crate) mod with_item;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::prelude::*;
|
||||
use crate::FormatNodeRule;
|
||||
use ruff_formatter::write;
|
||||
use ruff_python_ast::Arg;
|
||||
use ruff_python_ast::Parameter;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatArg;
|
||||
pub struct FormatParameter;
|
||||
|
||||
impl FormatNodeRule<Arg> for FormatArg {
|
||||
fn fmt_fields(&self, item: &Arg, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let Arg {
|
||||
impl FormatNodeRule<Parameter> for FormatParameter {
|
||||
fn fmt_fields(&self, item: &Parameter, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let Parameter {
|
||||
range: _,
|
||||
arg,
|
||||
annotation,
|
|
@ -1,15 +1,15 @@
|
|||
use ruff_formatter::write;
|
||||
use ruff_python_ast::ArgWithDefault;
|
||||
use ruff_python_ast::ParameterWithDefault;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::FormatNodeRule;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatArgWithDefault;
|
||||
pub struct FormatParameterWithDefault;
|
||||
|
||||
impl FormatNodeRule<ArgWithDefault> for FormatArgWithDefault {
|
||||
fn fmt_fields(&self, item: &ArgWithDefault, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let ArgWithDefault {
|
||||
impl FormatNodeRule<ParameterWithDefault> for FormatParameterWithDefault {
|
||||
fn fmt_fields(&self, item: &ParameterWithDefault, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let ParameterWithDefault {
|
||||
range: _,
|
||||
def,
|
||||
default,
|
|
@ -1,6 +1,6 @@
|
|||
use std::usize;
|
||||
|
||||
use ruff_python_ast::{Arguments, Ranged};
|
||||
use ruff_python_ast::{Parameters, Ranged};
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use ruff_formatter::{format_args, write, FormatRuleWithOptions};
|
||||
|
@ -17,14 +17,14 @@ use crate::prelude::*;
|
|||
use crate::FormatNodeRule;
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Default)]
|
||||
pub enum ArgumentsParentheses {
|
||||
/// By default, arguments will always preserve their surrounding parentheses.
|
||||
pub enum ParametersParentheses {
|
||||
/// By default, parameters will always preserve their surrounding parentheses.
|
||||
#[default]
|
||||
Preserve,
|
||||
|
||||
/// Handle special cases where parentheses should never be used.
|
||||
///
|
||||
/// An example where parentheses are never used for arguments would be with lambda
|
||||
/// An example where parentheses are never used for parameters would be with lambda
|
||||
/// expressions. The following is invalid syntax:
|
||||
/// ```python
|
||||
/// lambda (x, y, z): ...
|
||||
|
@ -37,12 +37,12 @@ pub enum ArgumentsParentheses {
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatArguments {
|
||||
parentheses: ArgumentsParentheses,
|
||||
pub struct FormatParameters {
|
||||
parentheses: ParametersParentheses,
|
||||
}
|
||||
|
||||
impl FormatRuleWithOptions<Arguments, PyFormatContext<'_>> for FormatArguments {
|
||||
type Options = ArgumentsParentheses;
|
||||
impl FormatRuleWithOptions<Parameters, PyFormatContext<'_>> for FormatParameters {
|
||||
type Options = ParametersParentheses;
|
||||
|
||||
fn with_options(mut self, options: Self::Options) -> Self {
|
||||
self.parentheses = options;
|
||||
|
@ -50,9 +50,9 @@ impl FormatRuleWithOptions<Arguments, PyFormatContext<'_>> for FormatArguments {
|
|||
}
|
||||
}
|
||||
|
||||
impl FormatNodeRule<Arguments> for FormatArguments {
|
||||
fn fmt_fields(&self, item: &Arguments, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let Arguments {
|
||||
impl FormatNodeRule<Parameters> for FormatParameters {
|
||||
fn fmt_fields(&self, item: &Parameters, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let Parameters {
|
||||
range: _,
|
||||
posonlyargs,
|
||||
args,
|
||||
|
@ -70,10 +70,10 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
let mut joiner = f.join_with(separator);
|
||||
let mut last_node: Option<AnyNodeRef> = None;
|
||||
|
||||
for arg_with_default in posonlyargs {
|
||||
joiner.entry(&arg_with_default.format());
|
||||
for parameter_with_default in posonlyargs {
|
||||
joiner.entry(¶meter_with_default.format());
|
||||
|
||||
last_node = Some(arg_with_default.into());
|
||||
last_node = Some(parameter_with_default.into());
|
||||
}
|
||||
|
||||
let slash_comments_end = if posonlyargs.is_empty() {
|
||||
|
@ -86,7 +86,7 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
comment.slice().range(),
|
||||
comment.line_position(),
|
||||
)
|
||||
.expect("Unexpected dangling comment type in function arguments");
|
||||
.expect("Unexpected dangling comment type in function parameters");
|
||||
matches!(
|
||||
assignment,
|
||||
ArgumentSeparatorCommentLocation::SlashLeading
|
||||
|
@ -100,10 +100,10 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
slash_comments_end
|
||||
};
|
||||
|
||||
for arg_with_default in args {
|
||||
joiner.entry(&arg_with_default.format());
|
||||
for parameter_with_default in args {
|
||||
joiner.entry(¶meter_with_default.format());
|
||||
|
||||
last_node = Some(arg_with_default.into());
|
||||
last_node = Some(parameter_with_default.into());
|
||||
}
|
||||
|
||||
// kw only args need either a `*args` ahead of them capturing all var args or a `*`
|
||||
|
@ -139,10 +139,10 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
});
|
||||
}
|
||||
|
||||
for arg_with_default in kwonlyargs {
|
||||
joiner.entry(&arg_with_default.format());
|
||||
for parameter_with_default in kwonlyargs {
|
||||
joiner.entry(¶meter_with_default.format());
|
||||
|
||||
last_node = Some(arg_with_default.into());
|
||||
last_node = Some(parameter_with_default.into());
|
||||
}
|
||||
|
||||
if let Some(kwarg) = kwarg {
|
||||
|
@ -168,7 +168,7 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
// # Never expands, the comma is always preserved
|
||||
// x2 = lambda y,: 1
|
||||
// ```
|
||||
if self.parentheses == ArgumentsParentheses::Never {
|
||||
if self.parentheses == ParametersParentheses::Never {
|
||||
// For lambdas (no parentheses), preserve the trailing comma. It doesn't
|
||||
// behave like a magic trailing comma, it's just preserved
|
||||
if has_trailing_comma(item, last_node, f.context().source()) {
|
||||
|
@ -190,16 +190,16 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
|
||||
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
|
||||
|
||||
let num_arguments = posonlyargs.len()
|
||||
let num_parameters = posonlyargs.len()
|
||||
+ args.len()
|
||||
+ usize::from(vararg.is_some())
|
||||
+ kwonlyargs.len()
|
||||
+ usize::from(kwarg.is_some());
|
||||
|
||||
if self.parentheses == ArgumentsParentheses::Never {
|
||||
if self.parentheses == ParametersParentheses::Never {
|
||||
write!(f, [group(&format_inner)])
|
||||
} else if num_arguments == 0 {
|
||||
// No arguments, format any dangling comments between `()`
|
||||
} else if num_parameters == 0 {
|
||||
// No parameters, format any dangling comments between `()`
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
|
@ -213,7 +213,7 @@ impl FormatNodeRule<Arguments> for FormatArguments {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_dangling_comments(&self, _node: &Arguments, _f: &mut PyFormatter) -> FormatResult<()> {
|
||||
fn fmt_dangling_comments(&self, _node: &Parameters, _f: &mut PyFormatter) -> FormatResult<()> {
|
||||
// Handled in `fmt_fields`
|
||||
Ok(())
|
||||
}
|
||||
|
@ -283,18 +283,18 @@ pub(crate) struct ArgumentSeparator {
|
|||
/// Returns slash and star
|
||||
pub(crate) fn find_argument_separators(
|
||||
contents: &str,
|
||||
arguments: &Arguments,
|
||||
parameters: &Parameters,
|
||||
) -> (Option<ArgumentSeparator>, Option<ArgumentSeparator>) {
|
||||
// We only compute preceding_end and token location here since following_start depends on the
|
||||
// star location, but the star location depends on slash's position
|
||||
let slash = if let Some(preceding_end) = arguments.posonlyargs.last().map(Ranged::end) {
|
||||
let slash = if let Some(preceding_end) = parameters.posonlyargs.last().map(Ranged::end) {
|
||||
// ```text
|
||||
// def f(a1=1, a2=2, /, a3, a4): pass
|
||||
// ^^^^^^^^^^^ the range (defaults)
|
||||
// def f(a1, a2, /, a3, a4): pass
|
||||
// ^^^^^^^^^^^^ the range (no default)
|
||||
// ```
|
||||
let range = TextRange::new(preceding_end, arguments.end());
|
||||
let range = TextRange::new(preceding_end, parameters.end());
|
||||
let mut tokens = SimpleTokenizer::new(contents, range).skip_trivia();
|
||||
|
||||
let comma = tokens
|
||||
|
@ -312,22 +312,22 @@ pub(crate) fn find_argument_separators(
|
|||
};
|
||||
|
||||
// If we have a vararg we have a node that the comments attach to
|
||||
let star = if arguments.vararg.is_some() {
|
||||
let star = if parameters.vararg.is_some() {
|
||||
// When the vararg is present the comments attach there and we don't need to do manual
|
||||
// formatting
|
||||
None
|
||||
} else if let Some(first_keyword_argument) = arguments.kwonlyargs.first() {
|
||||
} else if let Some(first_keyword_argument) = parameters.kwonlyargs.first() {
|
||||
// Check in that order:
|
||||
// * `f(a, /, b, *, c)` and `f(a=1, /, b=2, *, c)`
|
||||
// * `f(a, /, *, b)`
|
||||
// * `f(*, b)` (else branch)
|
||||
let after_arguments = arguments
|
||||
let after_parameters = parameters
|
||||
.args
|
||||
.last()
|
||||
.map(|arg| arg.range.end())
|
||||
.or(slash.map(|(_, slash)| slash.end()));
|
||||
if let Some(preceding_end) = after_arguments {
|
||||
let range = TextRange::new(preceding_end, arguments.end());
|
||||
if let Some(preceding_end) = after_parameters {
|
||||
let range = TextRange::new(preceding_end, parameters.end());
|
||||
let mut tokens = SimpleTokenizer::new(contents, range).skip_trivia();
|
||||
|
||||
let comma = tokens
|
||||
|
@ -345,7 +345,7 @@ pub(crate) fn find_argument_separators(
|
|||
following_start: first_keyword_argument.start(),
|
||||
})
|
||||
} else {
|
||||
let mut tokens = SimpleTokenizer::new(contents, arguments.range).skip_trivia();
|
||||
let mut tokens = SimpleTokenizer::new(contents, parameters.range).skip_trivia();
|
||||
|
||||
let lparen = tokens
|
||||
.next()
|
||||
|
@ -356,7 +356,7 @@ pub(crate) fn find_argument_separators(
|
|||
.expect("The function definition can't end here");
|
||||
debug_assert!(star.kind() == SimpleTokenKind::Star, "{star:?}");
|
||||
Some(ArgumentSeparator {
|
||||
preceding_end: arguments.range.start(),
|
||||
preceding_end: parameters.range.start(),
|
||||
separator: star.range,
|
||||
following_start: first_keyword_argument.start(),
|
||||
})
|
||||
|
@ -371,13 +371,13 @@ pub(crate) fn find_argument_separators(
|
|||
// * `f(a, /, *b)`
|
||||
// * `f(a, /, *, b)`
|
||||
// * `f(a, /)`
|
||||
let slash_following_start = arguments
|
||||
let slash_following_start = parameters
|
||||
.args
|
||||
.first()
|
||||
.map(Ranged::start)
|
||||
.or(arguments.vararg.as_ref().map(|first| first.start()))
|
||||
.or(parameters.vararg.as_ref().map(|first| first.start()))
|
||||
.or(star.as_ref().map(|star| star.separator.start()))
|
||||
.unwrap_or(arguments.end());
|
||||
.unwrap_or(parameters.end());
|
||||
let slash = slash.map(|(preceding_end, slash)| ArgumentSeparator {
|
||||
preceding_end,
|
||||
separator: slash,
|
||||
|
@ -387,13 +387,13 @@ pub(crate) fn find_argument_separators(
|
|||
(slash, star)
|
||||
}
|
||||
|
||||
/// Locates positional only arguments separator `/` or the keywords only arguments
|
||||
/// Locates positional only parameters separator `/` or the keywords only parameters
|
||||
/// separator `*` comments.
|
||||
///
|
||||
/// ```python
|
||||
/// def test(
|
||||
/// a,
|
||||
/// # Positional only arguments after here
|
||||
/// # Positional only parameters after here
|
||||
/// /, # trailing positional argument comment.
|
||||
/// b,
|
||||
/// ):
|
||||
|
@ -403,7 +403,7 @@ pub(crate) fn find_argument_separators(
|
|||
/// ```python
|
||||
/// def f(
|
||||
/// a="",
|
||||
/// # Keyword only arguments only after here
|
||||
/// # Keyword only parameters only after here
|
||||
/// *, # trailing keyword argument comment.
|
||||
/// b="",
|
||||
/// ):
|
||||
|
@ -439,43 +439,43 @@ pub(crate) fn find_argument_separators(
|
|||
///
|
||||
/// ```text
|
||||
/// def f(a1, a2): pass
|
||||
/// ^^^^^^ arguments (args)
|
||||
/// ^^^^^^ parameters (args)
|
||||
/// ```
|
||||
/// Use a star to separate keyword only arguments:
|
||||
/// Use a star to separate keyword only parameters:
|
||||
/// ```text
|
||||
/// def f(a1, a2, *, a3, a4): pass
|
||||
/// ^^^^^^ arguments (args)
|
||||
/// ^^^^^^ keyword only arguments (kwargs)
|
||||
/// ^^^^^^ parameters (args)
|
||||
/// ^^^^^^ keyword only parameters (kwargs)
|
||||
/// ```
|
||||
/// Use a slash to separate positional only arguments. Note that this changes the arguments left
|
||||
/// of the slash while the star change the arguments right of it:
|
||||
/// Use a slash to separate positional only parameters. Note that this changes the parameters left
|
||||
/// of the slash while the star change the parameters right of it:
|
||||
/// ```text
|
||||
/// def f(a1, a2, /, a3, a4): pass
|
||||
/// ^^^^^^ positional only arguments (posonlyargs)
|
||||
/// ^^^^^^ arguments (args)
|
||||
/// ^^^^^^ positional only parameters (posonlyargs)
|
||||
/// ^^^^^^ parameters (args)
|
||||
/// ```
|
||||
/// You can combine both:
|
||||
/// ```text
|
||||
/// def f(a1, a2, /, a3, a4, *, a5, a6): pass
|
||||
/// ^^^^^^ positional only arguments (posonlyargs)
|
||||
/// ^^^^^^ arguments (args)
|
||||
/// ^^^^^^ keyword only arguments (kwargs)
|
||||
/// ^^^^^^ positional only parameters (posonlyargs)
|
||||
/// ^^^^^^ parameters (args)
|
||||
/// ^^^^^^ keyword only parameters (kwargs)
|
||||
/// ```
|
||||
/// They can all have defaults, meaning that the preceding node ends at the default instead of the
|
||||
/// argument itself:
|
||||
/// ```text
|
||||
/// def f(a1=1, a2=2, /, a3=3, a4=4, *, a5=5, a6=6): pass
|
||||
/// ^ ^ ^ ^ ^ ^ defaults
|
||||
/// ^^^^^^^^^^ positional only arguments (posonlyargs)
|
||||
/// ^^^^^^^^^^ arguments (args)
|
||||
/// ^^^^^^^^^^ keyword only arguments (kwargs)
|
||||
/// ^^^^^^^^^^ positional only parameters (posonlyargs)
|
||||
/// ^^^^^^^^^^ parameters (args)
|
||||
/// ^^^^^^^^^^ keyword only parameters (kwargs)
|
||||
/// ```
|
||||
/// An especially difficult case is having no regular arguments, so comments from both slash and
|
||||
/// An especially difficult case is having no regular parameters, so comments from both slash and
|
||||
/// star will attach to either a2 or a3 and the next token is incorrect.
|
||||
/// ```text
|
||||
/// def f(a1, a2, /, *, a3, a4): pass
|
||||
/// ^^^^^^ positional only arguments (posonlyargs)
|
||||
/// ^^^^^^ keyword only arguments (kwargs)
|
||||
/// ^^^^^^ positional only parameters (posonlyargs)
|
||||
/// ^^^^^^ keyword only parameters (kwargs)
|
||||
/// ```
|
||||
pub(crate) fn assign_argument_separator_comment_placement(
|
||||
slash: Option<&ArgumentSeparator>,
|
||||
|
@ -583,27 +583,31 @@ pub(crate) enum ArgumentSeparatorCommentLocation {
|
|||
StarTrailing,
|
||||
}
|
||||
|
||||
fn has_trailing_comma(arguments: &Arguments, last_node: Option<AnyNodeRef>, source: &str) -> bool {
|
||||
fn has_trailing_comma(
|
||||
parameters: &Parameters,
|
||||
last_node: Option<AnyNodeRef>,
|
||||
source: &str,
|
||||
) -> bool {
|
||||
// No nodes, no trailing comma
|
||||
let Some(last_node) = last_node else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let ends_with_pos_only_argument_separator = !arguments.posonlyargs.is_empty()
|
||||
&& arguments.args.is_empty()
|
||||
&& arguments.vararg.is_none()
|
||||
&& arguments.kwonlyargs.is_empty()
|
||||
&& arguments.kwarg.is_none();
|
||||
let ends_with_pos_only_argument_separator = !parameters.posonlyargs.is_empty()
|
||||
&& parameters.args.is_empty()
|
||||
&& parameters.vararg.is_none()
|
||||
&& parameters.kwonlyargs.is_empty()
|
||||
&& parameters.kwarg.is_none();
|
||||
|
||||
let mut tokens = SimpleTokenizer::starts_at(last_node.end(), source).skip_trivia();
|
||||
// `def a(b, c, /): ... `
|
||||
// The slash lacks its own node
|
||||
if ends_with_pos_only_argument_separator {
|
||||
let comma = tokens.next();
|
||||
assert!(matches!(comma, Some(SimpleToken { kind: SimpleTokenKind::Comma, .. })), "The last positional only argument must be separated by a `,` from the positional only arguments separator `/` but found '{comma:?}'.");
|
||||
assert!(matches!(comma, Some(SimpleToken { kind: SimpleTokenKind::Comma, .. })), "The last positional only argument must be separated by a `,` from the positional only parameters separator `/` but found '{comma:?}'.");
|
||||
|
||||
let slash = tokens.next();
|
||||
assert!(matches!(slash, Some(SimpleToken { kind: SimpleTokenKind::Slash, .. })), "The positional argument separator must be present for a function that has positional only arguments but found '{slash:?}'.");
|
||||
assert!(matches!(slash, Some(SimpleToken { kind: SimpleTokenKind::Slash, .. })), "The positional argument separator must be present for a function that has positional only parameters but found '{slash:?}'.");
|
||||
}
|
||||
|
||||
tokens
|
Loading…
Add table
Add a link
Reference in a new issue