Improve internal docs for various string-node APIs (#16256)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions

This commit is contained in:
Alex Waygood 2025-02-19 16:13:45 +00:00 committed by GitHub
parent 25920fe489
commit 16d0625dfb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -811,7 +811,8 @@ pub struct DebugText {
pub trailing: String, 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 /// This type differs from the original Python AST ([JoinedStr]) in that it
/// doesn't join the implicitly concatenated parts into a single string. Instead, /// doesn't join the implicitly concatenated parts into a single string. Instead,
@ -842,7 +843,7 @@ pub struct FStringValue {
} }
impl 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 { pub fn single(value: FString) -> Self {
Self { Self {
inner: FStringValueInner::Single(FStringPart::FString(value)), inner: FStringValueInner::Single(FStringPart::FString(value)),
@ -854,9 +855,13 @@ impl FStringValue {
/// ///
/// # Panics /// # 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<FStringPart>) -> Self { pub fn concatenated(values: Vec<FStringPart>) -> Self {
assert!(values.len() > 1); assert!(
values.len() > 1,
"Use `FStringValue::single` to create single-part f-strings"
);
Self { Self {
inner: FStringValueInner::Concatenated(values), inner: FStringValueInner::Concatenated(values),
} }
@ -896,7 +901,7 @@ impl FStringValue {
/// Returns an iterator over the [`StringLiteral`] parts contained in this value. /// 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 /// ```python
/// "foo" f"bar {x}" "baz" f"qux" /// "foo" f"bar {x}" "baz" f"qux"
@ -909,7 +914,7 @@ impl FStringValue {
/// Returns an iterator over the [`FString`] parts contained in this value. /// 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 /// ```python
/// "foo" f"bar {x}" "baz" f"qux" /// "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 /// An AST node that represents either a single-part string literal
/// concatenated string literals. /// or an implicitly concatenated string literal.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ExprStringLiteral { pub struct ExprStringLiteral {
pub range: TextRange, pub range: TextRange,
@ -1307,7 +1312,7 @@ pub struct StringLiteralValue {
} }
impl 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 { pub fn single(string: StringLiteral) -> Self {
Self { Self {
inner: StringLiteralValueInner::Single(string), inner: StringLiteralValueInner::Single(string),
@ -1331,10 +1336,13 @@ impl StringLiteralValue {
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if `strings` is less than 2. Use [`StringLiteralValue::single`] /// Panics if `strings` has less than 2 elements.
/// instead. /// Use [`StringLiteralValue::single`] instead.
pub fn concatenated(strings: Vec<StringLiteral>) -> Self { pub fn concatenated(strings: Vec<StringLiteral>) -> Self {
assert!(strings.len() > 1); assert!(
strings.len() > 1,
"Use `StringLiteralValue::single` to create single-part strings"
);
Self { Self {
inner: StringLiteralValueInner::Concatenated(ConcatenatedStringLiteral { inner: StringLiteralValueInner::Concatenated(ConcatenatedStringLiteral {
strings, strings,
@ -1348,10 +1356,14 @@ impl StringLiteralValue {
matches!(self.inner, StringLiteralValueInner::Concatenated(_)) 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 /// 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 { pub fn is_unicode(&self) -> bool {
self.iter() self.iter()
.next() .next()
@ -1385,7 +1397,11 @@ impl StringLiteralValue {
self.as_mut_slice().iter_mut() 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 { pub fn is_empty(&self) -> bool {
self.len() == 0 self.len() == 0
} }
@ -1684,7 +1700,7 @@ impl From<StringLiteral> for Expr {
/// implicitly concatenated string. /// implicitly concatenated string.
#[derive(Clone)] #[derive(Clone)]
struct ConcatenatedStringLiteral { struct ConcatenatedStringLiteral {
/// Each string literal that makes up the concatenated string. /// The individual [`StringLiteral`] parts that make up the concatenated string.
strings: Vec<StringLiteral>, strings: Vec<StringLiteral>,
/// The concatenated string value. /// The concatenated string value.
value: OnceLock<Box<str>>, value: OnceLock<Box<str>>,
@ -1722,8 +1738,8 @@ impl Debug for ConcatenatedStringLiteral {
} }
} }
/// An AST node that represents either a single bytes literal or an implicitly /// An AST node that represents either a single-part bytestring literal
/// concatenated bytes literals. /// or an implicitly concatenated bytestring literal.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ExprBytesLiteral { pub struct ExprBytesLiteral {
pub range: TextRange, pub range: TextRange,
@ -1748,28 +1764,31 @@ pub struct BytesLiteralValue {
} }
impl 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 { pub fn single(value: BytesLiteral) -> Self {
Self { Self {
inner: BytesLiteralValueInner::Single(value), inner: BytesLiteralValueInner::Single(value),
} }
} }
/// Creates a new bytes literal with the given values that represents an /// Creates a new bytestring literal with the given values that represents an
/// implicitly concatenated bytes. /// implicitly concatenated bytestring.
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if `values` is less than 2. Use [`BytesLiteralValue::single`] /// Panics if `values` has less than 2 elements.
/// instead. /// Use [`BytesLiteralValue::single`] instead.
pub fn concatenated(values: Vec<BytesLiteral>) -> Self { pub fn concatenated(values: Vec<BytesLiteral>) -> Self {
assert!(values.len() > 1); assert!(
values.len() > 1,
"Use `BytesLiteralValue::single` to create single-part bytestrings"
);
Self { Self {
inner: BytesLiteralValueInner::Concatenated(values), 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 { pub const fn is_implicit_concatenated(&self) -> bool {
matches!(self.inner, BytesLiteralValueInner::Concatenated(_)) matches!(self.inner, BytesLiteralValueInner::Concatenated(_))
} }
@ -1801,17 +1820,21 @@ impl BytesLiteralValue {
self.as_mut_slice().iter_mut() 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 { pub fn is_empty(&self) -> bool {
self.iter().all(|part| part.is_empty()) 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 { pub fn len(&self) -> usize {
self.iter().map(|part| part.len()).sum() 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<Item = u8> + '_ { pub fn bytes(&self) -> impl Iterator<Item = u8> + '_ {
self.iter().flat_map(|part| part.as_slice().iter().copied()) 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`]. /// An internal representation of [`BytesLiteralValue`].
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
enum BytesLiteralValueInner { enum BytesLiteralValueInner {
/// A single bytes literal i.e., `b"foo"`. /// A single-part bytestring literal i.e., `b"foo"`.
Single(BytesLiteral), 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<BytesLiteral>), Concatenated(Vec<BytesLiteral>),
} }