From 16d0625dfb7c62afdf773e38b62eb4ccf71e01bc Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Wed, 19 Feb 2025 16:13:45 +0000 Subject: [PATCH] Improve internal docs for various string-node APIs (#16256) --- crates/ruff_python_ast/src/nodes.rs | 83 ++++++++++++++++++----------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/crates/ruff_python_ast/src/nodes.rs b/crates/ruff_python_ast/src/nodes.rs index 76cd0ae7d3..7463fe5068 100644 --- a/crates/ruff_python_ast/src/nodes.rs +++ b/crates/ruff_python_ast/src/nodes.rs @@ -811,7 +811,8 @@ pub struct DebugText { pub trailing: String, } -/// An AST node used to represent an f-string. +/// An AST node that represents either a single-part f-string literal +/// or an implicitly concatenated f-string literal. /// /// This type differs from the original Python AST ([JoinedStr]) in that it /// doesn't join the implicitly concatenated parts into a single string. Instead, @@ -842,7 +843,7 @@ pub struct FStringValue { } impl FStringValue { - /// Creates a new f-string with the given value. + /// Creates a new f-string literal with a single [`FString`] part. pub fn single(value: FString) -> Self { Self { inner: FStringValueInner::Single(FStringPart::FString(value)), @@ -854,9 +855,13 @@ impl FStringValue { /// /// # Panics /// - /// Panics if `values` is less than 2. Use [`FStringValue::single`] instead. + /// Panics if `values` has less than 2 elements. + /// Use [`FStringValue::single`] instead. pub fn concatenated(values: Vec) -> Self { - assert!(values.len() > 1); + assert!( + values.len() > 1, + "Use `FStringValue::single` to create single-part f-strings" + ); Self { inner: FStringValueInner::Concatenated(values), } @@ -896,7 +901,7 @@ impl FStringValue { /// Returns an iterator over the [`StringLiteral`] parts contained in this value. /// - /// Note that this doesn't nest into the f-string parts. For example, + /// Note that this doesn't recurse into the f-string parts. For example, /// /// ```python /// "foo" f"bar {x}" "baz" f"qux" @@ -909,7 +914,7 @@ impl FStringValue { /// Returns an iterator over the [`FString`] parts contained in this value. /// - /// Note that this doesn't nest into the f-string parts. For example, + /// Note that this doesn't recurse into the f-string parts. For example, /// /// ```python /// "foo" f"bar {x}" "baz" f"qux" @@ -1281,8 +1286,8 @@ impl fmt::Debug for FStringElements { } } -/// An AST node that represents either a single string literal or an implicitly -/// concatenated string literals. +/// An AST node that represents either a single-part string literal +/// or an implicitly concatenated string literal. #[derive(Clone, Debug, PartialEq)] pub struct ExprStringLiteral { pub range: TextRange, @@ -1307,7 +1312,7 @@ pub struct StringLiteralValue { } impl StringLiteralValue { - /// Creates a new single string literal with the given value. + /// Creates a new string literal with a single [`StringLiteral`] part. pub fn single(string: StringLiteral) -> Self { Self { inner: StringLiteralValueInner::Single(string), @@ -1331,10 +1336,13 @@ impl StringLiteralValue { /// /// # Panics /// - /// Panics if `strings` is less than 2. Use [`StringLiteralValue::single`] - /// instead. + /// Panics if `strings` has less than 2 elements. + /// Use [`StringLiteralValue::single`] instead. pub fn concatenated(strings: Vec) -> Self { - assert!(strings.len() > 1); + assert!( + strings.len() > 1, + "Use `StringLiteralValue::single` to create single-part strings" + ); Self { inner: StringLiteralValueInner::Concatenated(ConcatenatedStringLiteral { strings, @@ -1348,10 +1356,14 @@ impl StringLiteralValue { matches!(self.inner, StringLiteralValueInner::Concatenated(_)) } - /// Returns `true` if the string literal is a unicode string. + /// Returns `true` if the string literal has a `u` prefix, e.g. `u"foo"`. + /// + /// Although all strings in Python 3 are valid unicode (and the `u` prefix + /// is only retained for backwards compatibility), these strings are known as + /// "unicode strings". /// /// For an implicitly concatenated string, it returns `true` only if the first - /// string literal is a unicode string. + /// [`StringLiteral`] has the `u` prefix. pub fn is_unicode(&self) -> bool { self.iter() .next() @@ -1385,7 +1397,11 @@ impl StringLiteralValue { self.as_mut_slice().iter_mut() } - /// Returns `true` if the string literal value is empty. + /// Returns `true` if the node represents an empty string. + /// + /// Note that a [`StringLiteralValue`] node will always have >=1 [`StringLiteral`] parts + /// inside it. This method checks whether the value of the concatenated parts is equal + /// to the empty string, not whether the string has 0 parts inside it. pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -1684,7 +1700,7 @@ impl From for Expr { /// implicitly concatenated string. #[derive(Clone)] struct ConcatenatedStringLiteral { - /// Each string literal that makes up the concatenated string. + /// The individual [`StringLiteral`] parts that make up the concatenated string. strings: Vec, /// The concatenated string value. value: OnceLock>, @@ -1722,8 +1738,8 @@ impl Debug for ConcatenatedStringLiteral { } } -/// An AST node that represents either a single bytes literal or an implicitly -/// concatenated bytes literals. +/// An AST node that represents either a single-part bytestring literal +/// or an implicitly concatenated bytestring literal. #[derive(Clone, Debug, PartialEq)] pub struct ExprBytesLiteral { pub range: TextRange, @@ -1748,28 +1764,31 @@ pub struct BytesLiteralValue { } impl BytesLiteralValue { - /// Creates a new single bytes literal with the given value. + /// Create a new bytestring literal with a single [`BytesLiteral`] part. pub fn single(value: BytesLiteral) -> Self { Self { inner: BytesLiteralValueInner::Single(value), } } - /// Creates a new bytes literal with the given values that represents an - /// implicitly concatenated bytes. + /// Creates a new bytestring literal with the given values that represents an + /// implicitly concatenated bytestring. /// /// # Panics /// - /// Panics if `values` is less than 2. Use [`BytesLiteralValue::single`] - /// instead. + /// Panics if `values` has less than 2 elements. + /// Use [`BytesLiteralValue::single`] instead. pub fn concatenated(values: Vec) -> Self { - assert!(values.len() > 1); + assert!( + values.len() > 1, + "Use `BytesLiteralValue::single` to create single-part bytestrings" + ); Self { inner: BytesLiteralValueInner::Concatenated(values), } } - /// Returns `true` if the bytes literal is implicitly concatenated. + /// Returns `true` if the bytestring is implicitly concatenated. pub const fn is_implicit_concatenated(&self) -> bool { matches!(self.inner, BytesLiteralValueInner::Concatenated(_)) } @@ -1801,17 +1820,21 @@ impl BytesLiteralValue { self.as_mut_slice().iter_mut() } - /// Returns `true` if the concatenated bytes has a length of zero. + /// Return `true` if the node represents an empty bytestring. + /// + /// Note that a [`BytesLiteralValue`] node will always have >=1 [`BytesLiteral`] parts + /// inside it. This method checks whether the value of the concatenated parts is equal + /// to the empty bytestring, not whether the bytestring has 0 parts inside it. pub fn is_empty(&self) -> bool { self.iter().all(|part| part.is_empty()) } - /// Returns the length of the concatenated bytes. + /// Returns the length of the concatenated bytestring. pub fn len(&self) -> usize { self.iter().map(|part| part.len()).sum() } - /// Returns an iterator over the bytes of the concatenated bytes. + /// Returns an iterator over the bytes of the concatenated bytestring. pub fn bytes(&self) -> impl Iterator + '_ { self.iter().flat_map(|part| part.as_slice().iter().copied()) } @@ -1865,10 +1888,10 @@ impl<'a> From<&'a BytesLiteralValue> for Cow<'a, [u8]> { /// An internal representation of [`BytesLiteralValue`]. #[derive(Clone, Debug, PartialEq)] enum BytesLiteralValueInner { - /// A single bytes literal i.e., `b"foo"`. + /// A single-part bytestring literal i.e., `b"foo"`. Single(BytesLiteral), - /// An implicitly concatenated bytes literals i.e., `b"foo" b"bar"`. + /// An implicitly concatenated bytestring literal i.e., `b"foo" b"bar"`. Concatenated(Vec), }