1#![allow(clippy::derive_partial_eq_without_eq)]
2
3use crate::AtomicNodeIndex;
4use crate::generated::{
5 ExprBytesLiteral, ExprDict, ExprFString, ExprList, ExprName, ExprSet, ExprStringLiteral,
6 ExprTString, ExprTuple, PatternMatchAs, PatternMatchOr, StmtClassDef,
7};
8use std::borrow::Cow;
9use std::fmt;
10use std::fmt::Debug;
11use std::iter::FusedIterator;
12use std::ops::{Deref, DerefMut};
13use std::slice::{Iter, IterMut};
14use std::sync::OnceLock;
15
16use bitflags::bitflags;
17
18use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
19
20use crate::str_prefix::{
21 AnyStringPrefix, ByteStringPrefix, FStringPrefix, StringLiteralPrefix, TStringPrefix,
22};
23use crate::{
24 Expr, ExprRef, InterpolatedStringElement, LiteralExpressionRef, OperatorPrecedence, Pattern,
25 Stmt, TypeParam, int,
26 name::Name,
27 str::{Quote, TripleQuotes},
28};
29
30impl StmtClassDef {
31 pub fn bases(&self) -> &[Expr] {
33 match &self.arguments {
34 Some(arguments) => &arguments.args,
35 None => &[],
36 }
37 }
38
39 pub fn keywords(&self) -> &[Keyword] {
41 match &self.arguments {
42 Some(arguments) => &arguments.keywords,
43 None => &[],
44 }
45 }
46}
47
48#[derive(Clone, Debug, PartialEq)]
49#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
50pub struct ElifElseClause {
51 pub range: TextRange,
52 pub node_index: AtomicNodeIndex,
53 pub test: Option<Expr>,
54 pub body: Vec<Stmt>,
55}
56
57impl Expr {
58 pub fn is_literal_expr(&self) -> bool {
63 matches!(
64 self,
65 Expr::StringLiteral(_)
66 | Expr::BytesLiteral(_)
67 | Expr::NumberLiteral(_)
68 | Expr::BooleanLiteral(_)
69 | Expr::NoneLiteral(_)
70 | Expr::EllipsisLiteral(_)
71 )
72 }
73
74 pub fn as_literal_expr(&self) -> Option<LiteralExpressionRef<'_>> {
76 match self {
77 Expr::StringLiteral(expr) => Some(LiteralExpressionRef::StringLiteral(expr)),
78 Expr::BytesLiteral(expr) => Some(LiteralExpressionRef::BytesLiteral(expr)),
79 Expr::NumberLiteral(expr) => Some(LiteralExpressionRef::NumberLiteral(expr)),
80 Expr::BooleanLiteral(expr) => Some(LiteralExpressionRef::BooleanLiteral(expr)),
81 Expr::NoneLiteral(expr) => Some(LiteralExpressionRef::NoneLiteral(expr)),
82 Expr::EllipsisLiteral(expr) => Some(LiteralExpressionRef::EllipsisLiteral(expr)),
83 _ => None,
84 }
85 }
86
87 pub fn precedence(&self) -> OperatorPrecedence {
89 OperatorPrecedence::from(self)
90 }
91}
92
93impl ExprRef<'_> {
94 pub fn is_literal_expr(&self) -> bool {
96 matches!(
97 self,
98 ExprRef::StringLiteral(_)
99 | ExprRef::BytesLiteral(_)
100 | ExprRef::NumberLiteral(_)
101 | ExprRef::BooleanLiteral(_)
102 | ExprRef::NoneLiteral(_)
103 | ExprRef::EllipsisLiteral(_)
104 )
105 }
106
107 pub fn precedence(&self) -> OperatorPrecedence {
108 OperatorPrecedence::from(self)
109 }
110}
111
112#[derive(Debug, Clone, PartialEq)]
136#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
137pub struct DictItem {
138 pub key: Option<Expr>,
139 pub value: Expr,
140}
141
142impl DictItem {
143 fn key(&self) -> Option<&Expr> {
144 self.key.as_ref()
145 }
146
147 fn value(&self) -> &Expr {
148 &self.value
149 }
150}
151
152impl Ranged for DictItem {
153 fn range(&self) -> TextRange {
154 TextRange::new(
155 self.key.as_ref().map_or(self.value.start(), Ranged::start),
156 self.value.end(),
157 )
158 }
159}
160
161impl ExprDict {
162 pub fn iter_keys(&self) -> DictKeyIterator<'_> {
165 DictKeyIterator::new(&self.items)
166 }
167
168 pub fn iter_values(&self) -> DictValueIterator<'_> {
171 DictValueIterator::new(&self.items)
172 }
173
174 pub fn key(&self, n: usize) -> Option<&Expr> {
179 self.items[n].key()
180 }
181
182 pub fn value(&self, n: usize) -> &Expr {
187 self.items[n].value()
188 }
189
190 pub fn iter(&self) -> std::slice::Iter<'_, DictItem> {
191 self.items.iter()
192 }
193
194 pub fn len(&self) -> usize {
195 self.items.len()
196 }
197
198 pub fn is_empty(&self) -> bool {
199 self.items.is_empty()
200 }
201}
202
203impl<'a> IntoIterator for &'a ExprDict {
204 type IntoIter = std::slice::Iter<'a, DictItem>;
205 type Item = &'a DictItem;
206
207 fn into_iter(self) -> Self::IntoIter {
208 self.iter()
209 }
210}
211
212#[derive(Debug, Clone)]
213pub struct DictKeyIterator<'a> {
214 items: Iter<'a, DictItem>,
215}
216
217impl<'a> DictKeyIterator<'a> {
218 fn new(items: &'a [DictItem]) -> Self {
219 Self {
220 items: items.iter(),
221 }
222 }
223
224 pub fn is_empty(&self) -> bool {
225 self.len() == 0
226 }
227}
228
229impl<'a> Iterator for DictKeyIterator<'a> {
230 type Item = Option<&'a Expr>;
231
232 fn next(&mut self) -> Option<Self::Item> {
233 self.items.next().map(DictItem::key)
234 }
235
236 fn last(mut self) -> Option<Self::Item> {
237 self.next_back()
238 }
239
240 fn size_hint(&self) -> (usize, Option<usize>) {
241 self.items.size_hint()
242 }
243}
244
245impl DoubleEndedIterator for DictKeyIterator<'_> {
246 fn next_back(&mut self) -> Option<Self::Item> {
247 self.items.next_back().map(DictItem::key)
248 }
249}
250
251impl FusedIterator for DictKeyIterator<'_> {}
252impl ExactSizeIterator for DictKeyIterator<'_> {}
253
254#[derive(Debug, Clone)]
255pub struct DictValueIterator<'a> {
256 items: Iter<'a, DictItem>,
257}
258
259impl<'a> DictValueIterator<'a> {
260 fn new(items: &'a [DictItem]) -> Self {
261 Self {
262 items: items.iter(),
263 }
264 }
265
266 pub fn is_empty(&self) -> bool {
267 self.len() == 0
268 }
269}
270
271impl<'a> Iterator for DictValueIterator<'a> {
272 type Item = &'a Expr;
273
274 fn next(&mut self) -> Option<Self::Item> {
275 self.items.next().map(DictItem::value)
276 }
277
278 fn last(mut self) -> Option<Self::Item> {
279 self.next_back()
280 }
281
282 fn size_hint(&self) -> (usize, Option<usize>) {
283 self.items.size_hint()
284 }
285}
286
287impl DoubleEndedIterator for DictValueIterator<'_> {
288 fn next_back(&mut self) -> Option<Self::Item> {
289 self.items.next_back().map(DictItem::value)
290 }
291}
292
293impl FusedIterator for DictValueIterator<'_> {}
294impl ExactSizeIterator for DictValueIterator<'_> {}
295
296impl ExprSet {
297 pub fn iter(&self) -> std::slice::Iter<'_, Expr> {
298 self.elts.iter()
299 }
300
301 pub fn len(&self) -> usize {
302 self.elts.len()
303 }
304
305 pub fn is_empty(&self) -> bool {
306 self.elts.is_empty()
307 }
308}
309
310impl<'a> IntoIterator for &'a ExprSet {
311 type IntoIter = std::slice::Iter<'a, Expr>;
312 type Item = &'a Expr;
313
314 fn into_iter(self) -> Self::IntoIter {
315 self.iter()
316 }
317}
318
319#[derive(Clone, Debug, PartialEq)]
320#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
321pub struct InterpolatedStringFormatSpec {
322 pub range: TextRange,
323 pub node_index: AtomicNodeIndex,
324 pub elements: InterpolatedStringElements,
325}
326
327#[derive(Clone, Debug, PartialEq)]
329#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
330pub struct InterpolatedElement {
331 pub range: TextRange,
332 pub node_index: AtomicNodeIndex,
333 pub expression: Box<Expr>,
334 pub debug_text: Option<DebugText>,
335 pub conversion: ConversionFlag,
336 pub format_spec: Option<Box<InterpolatedStringFormatSpec>>,
337}
338
339#[derive(Clone, Debug, PartialEq)]
341#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
342pub struct InterpolatedStringLiteralElement {
343 pub range: TextRange,
344 pub node_index: AtomicNodeIndex,
345 pub value: Box<str>,
346}
347
348impl InterpolatedStringLiteralElement {
349 pub fn is_valid(&self) -> bool {
350 !self.value.is_empty()
351 }
352}
353
354impl Deref for InterpolatedStringLiteralElement {
355 type Target = str;
356
357 fn deref(&self) -> &Self::Target {
358 &self.value
359 }
360}
361
362#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, is_macro::Is)]
364#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
365#[repr(i8)]
366#[expect(clippy::cast_possible_wrap)]
367pub enum ConversionFlag {
368 None = -1, Str = b's' as i8,
372 Ascii = b'a' as i8,
374 Repr = b'r' as i8,
376}
377
378impl ConversionFlag {
379 pub fn to_byte(&self) -> Option<u8> {
380 match self {
381 Self::None => None,
382 flag => Some(*flag as u8),
383 }
384 }
385 pub fn to_char(&self) -> Option<char> {
386 Some(self.to_byte()? as char)
387 }
388}
389
390#[derive(Clone, Debug, PartialEq, Eq, Hash)]
391#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
392pub struct DebugText {
393 pub leading: String,
395 pub trailing: String,
397}
398
399impl ExprFString {
400 pub const fn as_single_part_fstring(&self) -> Option<&FString> {
403 match &self.value.inner {
404 FStringValueInner::Single(FStringPart::FString(fstring)) => Some(fstring),
405 _ => None,
406 }
407 }
408}
409
410#[derive(Clone, Debug, PartialEq)]
412#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
413pub struct FStringValue {
414 inner: FStringValueInner,
415}
416
417impl FStringValue {
418 pub fn single(value: FString) -> Self {
420 Self {
421 inner: FStringValueInner::Single(FStringPart::FString(value)),
422 }
423 }
424
425 pub fn concatenated(values: Vec<FStringPart>) -> Self {
433 assert!(
434 values.len() > 1,
435 "Use `FStringValue::single` to create single-part f-strings"
436 );
437 Self {
438 inner: FStringValueInner::Concatenated(values),
439 }
440 }
441
442 pub fn is_implicit_concatenated(&self) -> bool {
444 matches!(self.inner, FStringValueInner::Concatenated(_))
445 }
446
447 pub fn as_slice(&self) -> &[FStringPart] {
449 match &self.inner {
450 FStringValueInner::Single(part) => std::slice::from_ref(part),
451 FStringValueInner::Concatenated(parts) => parts,
452 }
453 }
454
455 fn as_mut_slice(&mut self) -> &mut [FStringPart] {
457 match &mut self.inner {
458 FStringValueInner::Single(part) => std::slice::from_mut(part),
459 FStringValueInner::Concatenated(parts) => parts,
460 }
461 }
462
463 pub fn iter(&self) -> Iter<'_, FStringPart> {
465 self.as_slice().iter()
466 }
467
468 pub fn iter_mut(&mut self) -> IterMut<'_, FStringPart> {
471 self.as_mut_slice().iter_mut()
472 }
473
474 pub fn literals(&self) -> impl Iterator<Item = &StringLiteral> {
484 self.iter().filter_map(|part| part.as_literal())
485 }
486
487 pub fn f_strings(&self) -> impl Iterator<Item = &FString> {
497 self.iter().filter_map(|part| part.as_f_string())
498 }
499
500 pub fn elements(&self) -> impl Iterator<Item = &InterpolatedStringElement> {
512 self.f_strings().flat_map(|fstring| fstring.elements.iter())
513 }
514
515 pub fn is_empty_literal(&self) -> bool {
521 match &self.inner {
522 FStringValueInner::Single(fstring_part) => fstring_part.is_empty_literal(),
523 FStringValueInner::Concatenated(fstring_parts) => {
524 fstring_parts.iter().all(FStringPart::is_empty_literal)
525 }
526 }
527 }
528}
529
530impl<'a> IntoIterator for &'a FStringValue {
531 type Item = &'a FStringPart;
532 type IntoIter = Iter<'a, FStringPart>;
533
534 fn into_iter(self) -> Self::IntoIter {
535 self.iter()
536 }
537}
538
539impl<'a> IntoIterator for &'a mut FStringValue {
540 type Item = &'a mut FStringPart;
541 type IntoIter = IterMut<'a, FStringPart>;
542 fn into_iter(self) -> Self::IntoIter {
543 self.iter_mut()
544 }
545}
546
547#[derive(Clone, Debug, PartialEq)]
549#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
550enum FStringValueInner {
551 Single(FStringPart),
556
557 Concatenated(Vec<FStringPart>),
559}
560
561#[derive(Clone, Debug, PartialEq, is_macro::Is)]
563#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
564pub enum FStringPart {
565 Literal(StringLiteral),
566 FString(FString),
567}
568
569impl FStringPart {
570 pub fn quote_style(&self) -> Quote {
571 match self {
572 Self::Literal(string_literal) => string_literal.flags.quote_style(),
573 Self::FString(f_string) => f_string.flags.quote_style(),
574 }
575 }
576
577 pub fn is_empty_literal(&self) -> bool {
578 match &self {
579 FStringPart::Literal(string_literal) => string_literal.value.is_empty(),
580 FStringPart::FString(f_string) => f_string.elements.is_empty(),
581 }
582 }
583}
584
585impl Ranged for FStringPart {
586 fn range(&self) -> TextRange {
587 match self {
588 FStringPart::Literal(string_literal) => string_literal.range(),
589 FStringPart::FString(f_string) => f_string.range(),
590 }
591 }
592}
593
594impl ExprTString {
595 pub const fn as_single_part_tstring(&self) -> Option<&TString> {
598 match &self.value.inner {
599 TStringValueInner::Single(tstring) => Some(tstring),
600 TStringValueInner::Concatenated(_) => None,
601 }
602 }
603}
604
605#[derive(Clone, Debug, PartialEq)]
607#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
608pub struct TStringValue {
609 inner: TStringValueInner,
610}
611
612impl TStringValue {
613 pub fn single(value: TString) -> Self {
615 Self {
616 inner: TStringValueInner::Single(value),
617 }
618 }
619
620 pub fn concatenated(values: Vec<TString>) -> Self {
628 assert!(
629 values.len() > 1,
630 "Use `TStringValue::single` to create single-part t-strings"
631 );
632 Self {
633 inner: TStringValueInner::Concatenated(values),
634 }
635 }
636
637 pub fn is_implicit_concatenated(&self) -> bool {
639 matches!(self.inner, TStringValueInner::Concatenated(_))
640 }
641
642 pub fn as_slice(&self) -> &[TString] {
644 match &self.inner {
645 TStringValueInner::Single(part) => std::slice::from_ref(part),
646 TStringValueInner::Concatenated(parts) => parts,
647 }
648 }
649
650 fn as_mut_slice(&mut self) -> &mut [TString] {
652 match &mut self.inner {
653 TStringValueInner::Single(part) => std::slice::from_mut(part),
654 TStringValueInner::Concatenated(parts) => parts,
655 }
656 }
657
658 pub fn iter(&self) -> Iter<'_, TString> {
660 self.as_slice().iter()
661 }
662
663 pub fn iter_mut(&mut self) -> IterMut<'_, TString> {
666 self.as_mut_slice().iter_mut()
667 }
668
669 pub fn elements(&self) -> impl Iterator<Item = &InterpolatedStringElement> {
681 self.iter().flat_map(|tstring| tstring.elements.iter())
682 }
683
684 pub fn is_empty_iterable(&self) -> bool {
694 match &self.inner {
695 TStringValueInner::Single(tstring) => tstring.is_empty(),
696 TStringValueInner::Concatenated(tstrings) => tstrings.iter().all(TString::is_empty),
697 }
698 }
699}
700
701impl<'a> IntoIterator for &'a TStringValue {
702 type Item = &'a TString;
703 type IntoIter = Iter<'a, TString>;
704
705 fn into_iter(self) -> Self::IntoIter {
706 self.iter()
707 }
708}
709
710impl<'a> IntoIterator for &'a mut TStringValue {
711 type Item = &'a mut TString;
712 type IntoIter = IterMut<'a, TString>;
713 fn into_iter(self) -> Self::IntoIter {
714 self.iter_mut()
715 }
716}
717
718#[derive(Clone, Debug, PartialEq)]
720#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
721enum TStringValueInner {
722 Single(TString),
724
725 Concatenated(Vec<TString>),
727}
728
729pub trait StringFlags: Copy {
730 fn quote_style(self) -> Quote;
732
733 fn triple_quotes(self) -> TripleQuotes;
734
735 fn prefix(self) -> AnyStringPrefix;
736
737 fn is_unclosed(self) -> bool;
738
739 fn is_triple_quoted(self) -> bool {
742 self.triple_quotes().is_yes()
743 }
744
745 fn quote_str(self) -> &'static str {
748 match (self.triple_quotes(), self.quote_style()) {
749 (TripleQuotes::Yes, Quote::Single) => "'''",
750 (TripleQuotes::Yes, Quote::Double) => r#"""""#,
751 (TripleQuotes::No, Quote::Single) => "'",
752 (TripleQuotes::No, Quote::Double) => "\"",
753 }
754 }
755
756 fn quote_len(self) -> TextSize {
760 if self.is_triple_quoted() {
761 TextSize::new(3)
762 } else {
763 TextSize::new(1)
764 }
765 }
766
767 fn opener_len(self) -> TextSize {
771 self.prefix().text_len() + self.quote_len()
772 }
773
774 fn closer_len(self) -> TextSize {
778 if self.is_unclosed() {
779 TextSize::default()
780 } else {
781 self.quote_len()
782 }
783 }
784
785 fn as_any_string_flags(self) -> AnyStringFlags {
786 AnyStringFlags::new(self.prefix(), self.quote_style(), self.triple_quotes())
787 .with_unclosed(self.is_unclosed())
788 }
789
790 fn display_contents(self, contents: &str) -> DisplayFlags<'_> {
791 DisplayFlags {
792 flags: self.as_any_string_flags(),
793 contents,
794 }
795 }
796}
797
798pub struct DisplayFlags<'a> {
799 flags: AnyStringFlags,
800 contents: &'a str,
801}
802
803impl std::fmt::Display for DisplayFlags<'_> {
804 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
805 write!(
806 f,
807 "{prefix}{quote}{contents}{quote}",
808 prefix = self.flags.prefix(),
809 quote = self.flags.quote_str(),
810 contents = self.contents
811 )
812 }
813}
814
815bitflags! {
816 #[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
817 struct InterpolatedStringFlagsInner: u8 {
818 const DOUBLE = 1 << 0;
822
823 const TRIPLE_QUOTED = 1 << 1;
827
828 const R_PREFIX_LOWER = 1 << 2;
831
832 const R_PREFIX_UPPER = 1 << 3;
838
839 const UNCLOSED = 1 << 4;
842 }
843}
844
845#[cfg(feature = "get-size")]
846impl get_size2::GetSize for InterpolatedStringFlagsInner {}
847
848#[derive(Copy, Clone, Eq, PartialEq, Hash)]
865#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
866pub struct FStringFlags(InterpolatedStringFlagsInner);
867
868impl FStringFlags {
869 pub fn empty() -> Self {
879 Self(InterpolatedStringFlagsInner::empty())
880 }
881
882 #[must_use]
883 pub fn with_quote_style(mut self, quote_style: Quote) -> Self {
884 self.0.set(
885 InterpolatedStringFlagsInner::DOUBLE,
886 quote_style.is_double(),
887 );
888 self
889 }
890
891 #[must_use]
892 pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self {
893 self.0.set(
894 InterpolatedStringFlagsInner::TRIPLE_QUOTED,
895 triple_quotes.is_yes(),
896 );
897 self
898 }
899
900 #[must_use]
901 pub fn with_unclosed(mut self, unclosed: bool) -> Self {
902 self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed);
903 self
904 }
905
906 #[must_use]
907 pub fn with_prefix(mut self, prefix: FStringPrefix) -> Self {
908 match prefix {
909 FStringPrefix::Regular => Self(
910 self.0
911 - InterpolatedStringFlagsInner::R_PREFIX_LOWER
912 - InterpolatedStringFlagsInner::R_PREFIX_UPPER,
913 ),
914 FStringPrefix::Raw { uppercase_r } => {
915 self.0
916 .set(InterpolatedStringFlagsInner::R_PREFIX_UPPER, uppercase_r);
917 self.0
918 .set(InterpolatedStringFlagsInner::R_PREFIX_LOWER, !uppercase_r);
919 self
920 }
921 }
922 }
923
924 pub const fn prefix(self) -> FStringPrefix {
925 if self
926 .0
927 .contains(InterpolatedStringFlagsInner::R_PREFIX_LOWER)
928 {
929 debug_assert!(
930 !self
931 .0
932 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER)
933 );
934 FStringPrefix::Raw { uppercase_r: false }
935 } else if self
936 .0
937 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER)
938 {
939 FStringPrefix::Raw { uppercase_r: true }
940 } else {
941 FStringPrefix::Regular
942 }
943 }
944}
945
946#[derive(Copy, Clone, Eq, PartialEq, Hash)]
968#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
969pub struct TStringFlags(InterpolatedStringFlagsInner);
970
971impl TStringFlags {
972 pub fn empty() -> Self {
982 Self(InterpolatedStringFlagsInner::empty())
983 }
984
985 #[must_use]
986 pub fn with_quote_style(mut self, quote_style: Quote) -> Self {
987 self.0.set(
988 InterpolatedStringFlagsInner::DOUBLE,
989 quote_style.is_double(),
990 );
991 self
992 }
993
994 #[must_use]
995 pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self {
996 self.0.set(
997 InterpolatedStringFlagsInner::TRIPLE_QUOTED,
998 triple_quotes.is_yes(),
999 );
1000 self
1001 }
1002
1003 #[must_use]
1004 pub fn with_unclosed(mut self, unclosed: bool) -> Self {
1005 self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed);
1006 self
1007 }
1008
1009 #[must_use]
1010 pub fn with_prefix(mut self, prefix: TStringPrefix) -> Self {
1011 match prefix {
1012 TStringPrefix::Regular => Self(
1013 self.0
1014 - InterpolatedStringFlagsInner::R_PREFIX_LOWER
1015 - InterpolatedStringFlagsInner::R_PREFIX_UPPER,
1016 ),
1017 TStringPrefix::Raw { uppercase_r } => {
1018 self.0
1019 .set(InterpolatedStringFlagsInner::R_PREFIX_UPPER, uppercase_r);
1020 self.0
1021 .set(InterpolatedStringFlagsInner::R_PREFIX_LOWER, !uppercase_r);
1022 self
1023 }
1024 }
1025 }
1026
1027 pub const fn prefix(self) -> TStringPrefix {
1028 if self
1029 .0
1030 .contains(InterpolatedStringFlagsInner::R_PREFIX_LOWER)
1031 {
1032 debug_assert!(
1033 !self
1034 .0
1035 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER)
1036 );
1037 TStringPrefix::Raw { uppercase_r: false }
1038 } else if self
1039 .0
1040 .contains(InterpolatedStringFlagsInner::R_PREFIX_UPPER)
1041 {
1042 TStringPrefix::Raw { uppercase_r: true }
1043 } else {
1044 TStringPrefix::Regular
1045 }
1046 }
1047}
1048
1049impl StringFlags for FStringFlags {
1050 fn triple_quotes(self) -> TripleQuotes {
1054 if self.0.contains(InterpolatedStringFlagsInner::TRIPLE_QUOTED) {
1055 TripleQuotes::Yes
1056 } else {
1057 TripleQuotes::No
1058 }
1059 }
1060
1061 fn quote_style(self) -> Quote {
1066 if self.0.contains(InterpolatedStringFlagsInner::DOUBLE) {
1067 Quote::Double
1068 } else {
1069 Quote::Single
1070 }
1071 }
1072
1073 fn prefix(self) -> AnyStringPrefix {
1074 AnyStringPrefix::Format(self.prefix())
1075 }
1076
1077 fn is_unclosed(self) -> bool {
1078 self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED)
1079 }
1080}
1081
1082impl fmt::Debug for FStringFlags {
1083 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1084 f.debug_struct("FStringFlags")
1085 .field("quote_style", &self.quote_style())
1086 .field("prefix", &self.prefix())
1087 .field("triple_quoted", &self.is_triple_quoted())
1088 .field("unclosed", &self.is_unclosed())
1089 .finish()
1090 }
1091}
1092
1093impl StringFlags for TStringFlags {
1094 fn triple_quotes(self) -> TripleQuotes {
1098 if self.0.contains(InterpolatedStringFlagsInner::TRIPLE_QUOTED) {
1099 TripleQuotes::Yes
1100 } else {
1101 TripleQuotes::No
1102 }
1103 }
1104
1105 fn quote_style(self) -> Quote {
1110 if self.0.contains(InterpolatedStringFlagsInner::DOUBLE) {
1111 Quote::Double
1112 } else {
1113 Quote::Single
1114 }
1115 }
1116
1117 fn prefix(self) -> AnyStringPrefix {
1118 AnyStringPrefix::Template(self.prefix())
1119 }
1120
1121 fn is_unclosed(self) -> bool {
1122 self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED)
1123 }
1124}
1125
1126impl fmt::Debug for TStringFlags {
1127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1128 f.debug_struct("TStringFlags")
1129 .field("quote_style", &self.quote_style())
1130 .field("prefix", &self.prefix())
1131 .field("triple_quoted", &self.is_triple_quoted())
1132 .field("unclosed", &self.is_unclosed())
1133 .finish()
1134 }
1135}
1136
1137#[derive(Clone, Debug, PartialEq)]
1139#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1140pub struct FString {
1141 pub range: TextRange,
1142 pub node_index: AtomicNodeIndex,
1143 pub elements: InterpolatedStringElements,
1144 pub flags: FStringFlags,
1145}
1146
1147impl From<FString> for Expr {
1148 fn from(payload: FString) -> Self {
1149 ExprFString {
1150 node_index: payload.node_index.clone(),
1151 range: payload.range,
1152 value: FStringValue::single(payload),
1153 }
1154 .into()
1155 }
1156}
1157
1158#[derive(Clone, Default, PartialEq)]
1160#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1161pub struct InterpolatedStringElements(Vec<InterpolatedStringElement>);
1162
1163impl InterpolatedStringElements {
1164 pub fn literals(&self) -> impl Iterator<Item = &InterpolatedStringLiteralElement> {
1166 self.iter().filter_map(|element| element.as_literal())
1167 }
1168
1169 pub fn interpolations(&self) -> impl Iterator<Item = &InterpolatedElement> {
1171 self.iter().filter_map(|element| element.as_interpolation())
1172 }
1173}
1174
1175impl From<Vec<InterpolatedStringElement>> for InterpolatedStringElements {
1176 fn from(elements: Vec<InterpolatedStringElement>) -> Self {
1177 InterpolatedStringElements(elements)
1178 }
1179}
1180
1181impl<'a> IntoIterator for &'a InterpolatedStringElements {
1182 type IntoIter = Iter<'a, InterpolatedStringElement>;
1183 type Item = &'a InterpolatedStringElement;
1184
1185 fn into_iter(self) -> Self::IntoIter {
1186 self.iter()
1187 }
1188}
1189
1190impl<'a> IntoIterator for &'a mut InterpolatedStringElements {
1191 type IntoIter = IterMut<'a, InterpolatedStringElement>;
1192 type Item = &'a mut InterpolatedStringElement;
1193
1194 fn into_iter(self) -> Self::IntoIter {
1195 self.iter_mut()
1196 }
1197}
1198
1199impl Deref for InterpolatedStringElements {
1200 type Target = [InterpolatedStringElement];
1201
1202 fn deref(&self) -> &Self::Target {
1203 &self.0
1204 }
1205}
1206
1207impl DerefMut for InterpolatedStringElements {
1208 fn deref_mut(&mut self) -> &mut Self::Target {
1209 &mut self.0
1210 }
1211}
1212
1213impl fmt::Debug for InterpolatedStringElements {
1214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1215 fmt::Debug::fmt(&self.0, f)
1216 }
1217}
1218
1219#[derive(Clone, Debug, PartialEq)]
1221#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1222pub struct TString {
1223 pub range: TextRange,
1224 pub node_index: AtomicNodeIndex,
1225 pub elements: InterpolatedStringElements,
1226 pub flags: TStringFlags,
1227}
1228
1229impl TString {
1230 pub fn quote_style(&self) -> Quote {
1231 self.flags.quote_style()
1232 }
1233
1234 pub fn is_empty(&self) -> bool {
1235 self.elements.is_empty()
1236 }
1237}
1238
1239impl From<TString> for Expr {
1240 fn from(payload: TString) -> Self {
1241 ExprTString {
1242 node_index: payload.node_index.clone(),
1243 range: payload.range,
1244 value: TStringValue::single(payload),
1245 }
1246 .into()
1247 }
1248}
1249
1250impl ExprStringLiteral {
1251 pub fn as_single_part_string(&self) -> Option<&StringLiteral> {
1254 match &self.value.inner {
1255 StringLiteralValueInner::Single(value) => Some(value),
1256 StringLiteralValueInner::Concatenated(_) => None,
1257 }
1258 }
1259}
1260
1261#[derive(Clone, Debug, PartialEq)]
1263#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1264pub struct StringLiteralValue {
1265 inner: StringLiteralValueInner,
1266}
1267
1268impl StringLiteralValue {
1269 pub fn single(string: StringLiteral) -> Self {
1271 Self {
1272 inner: StringLiteralValueInner::Single(string),
1273 }
1274 }
1275
1276 pub fn first_literal_flags(&self) -> StringLiteralFlags {
1280 self.iter()
1281 .next()
1282 .expect(
1283 "There should always be at least one string literal in an `ExprStringLiteral` node",
1284 )
1285 .flags
1286 }
1287
1288 pub fn concatenated(strings: Vec<StringLiteral>) -> Self {
1296 assert!(
1297 strings.len() > 1,
1298 "Use `StringLiteralValue::single` to create single-part strings"
1299 );
1300 Self {
1301 inner: StringLiteralValueInner::Concatenated(ConcatenatedStringLiteral {
1302 strings,
1303 value: OnceLock::new(),
1304 }),
1305 }
1306 }
1307
1308 pub const fn is_implicit_concatenated(&self) -> bool {
1310 matches!(self.inner, StringLiteralValueInner::Concatenated(_))
1311 }
1312
1313 pub fn is_unicode(&self) -> bool {
1322 self.iter()
1323 .next()
1324 .is_some_and(|part| part.flags.prefix().is_unicode())
1325 }
1326
1327 pub fn as_slice(&self) -> &[StringLiteral] {
1329 match &self.inner {
1330 StringLiteralValueInner::Single(value) => std::slice::from_ref(value),
1331 StringLiteralValueInner::Concatenated(value) => value.strings.as_slice(),
1332 }
1333 }
1334
1335 fn as_mut_slice(&mut self) -> &mut [StringLiteral] {
1337 match &mut self.inner {
1338 StringLiteralValueInner::Single(value) => std::slice::from_mut(value),
1339 StringLiteralValueInner::Concatenated(value) => value.strings.as_mut_slice(),
1340 }
1341 }
1342
1343 pub fn iter(&self) -> Iter<'_, StringLiteral> {
1345 self.as_slice().iter()
1346 }
1347
1348 pub fn iter_mut(&mut self) -> IterMut<'_, StringLiteral> {
1351 self.as_mut_slice().iter_mut()
1352 }
1353
1354 pub fn is_empty(&self) -> bool {
1360 self.len() == 0
1361 }
1362
1363 pub fn len(&self) -> usize {
1366 self.iter().fold(0, |acc, part| acc + part.value.len())
1367 }
1368
1369 pub fn chars(&self) -> impl Iterator<Item = char> + Clone + '_ {
1371 self.iter().flat_map(|part| part.value.chars())
1372 }
1373
1374 pub fn to_str(&self) -> &str {
1379 match &self.inner {
1380 StringLiteralValueInner::Single(value) => value.as_str(),
1381 StringLiteralValueInner::Concatenated(value) => value.to_str(),
1382 }
1383 }
1384}
1385
1386impl<'a> IntoIterator for &'a StringLiteralValue {
1387 type Item = &'a StringLiteral;
1388 type IntoIter = Iter<'a, StringLiteral>;
1389
1390 fn into_iter(self) -> Self::IntoIter {
1391 self.iter()
1392 }
1393}
1394
1395impl<'a> IntoIterator for &'a mut StringLiteralValue {
1396 type Item = &'a mut StringLiteral;
1397 type IntoIter = IterMut<'a, StringLiteral>;
1398 fn into_iter(self) -> Self::IntoIter {
1399 self.iter_mut()
1400 }
1401}
1402
1403impl PartialEq<str> for StringLiteralValue {
1404 fn eq(&self, other: &str) -> bool {
1405 if self.len() != other.len() {
1406 return false;
1407 }
1408 self.chars().zip(other.chars()).all(|(c1, c2)| c1 == c2)
1410 }
1411}
1412
1413impl fmt::Display for StringLiteralValue {
1414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1415 f.write_str(self.to_str())
1416 }
1417}
1418
1419#[derive(Clone, Debug, PartialEq)]
1421#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1422enum StringLiteralValueInner {
1423 Single(StringLiteral),
1425
1426 Concatenated(ConcatenatedStringLiteral),
1428}
1429
1430bitflags! {
1431 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
1432 struct StringLiteralFlagsInner: u8 {
1433 const DOUBLE = 1 << 0;
1436
1437 const TRIPLE_QUOTED = 1 << 1;
1440
1441 const U_PREFIX = 1 << 2;
1447
1448 const R_PREFIX_LOWER = 1 << 3;
1452
1453 const R_PREFIX_UPPER = 1 << 4;
1459
1460 const INVALID = 1 << 5;
1462
1463 const UNCLOSED = 1 << 6;
1465 }
1466}
1467
1468#[cfg(feature = "get-size")]
1469impl get_size2::GetSize for StringLiteralFlagsInner {}
1470
1471#[derive(Copy, Clone, Eq, PartialEq, Hash)]
1484#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1485pub struct StringLiteralFlags(StringLiteralFlagsInner);
1486
1487impl StringLiteralFlags {
1488 pub fn empty() -> Self {
1498 Self(StringLiteralFlagsInner::empty())
1499 }
1500
1501 #[must_use]
1502 pub fn with_quote_style(mut self, quote_style: Quote) -> Self {
1503 self.0
1504 .set(StringLiteralFlagsInner::DOUBLE, quote_style.is_double());
1505 self
1506 }
1507
1508 #[must_use]
1509 pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self {
1510 self.0.set(
1511 StringLiteralFlagsInner::TRIPLE_QUOTED,
1512 triple_quotes.is_yes(),
1513 );
1514 self
1515 }
1516
1517 #[must_use]
1518 pub fn with_unclosed(mut self, unclosed: bool) -> Self {
1519 self.0.set(StringLiteralFlagsInner::UNCLOSED, unclosed);
1520 self
1521 }
1522
1523 #[must_use]
1524 pub fn with_prefix(self, prefix: StringLiteralPrefix) -> Self {
1525 let StringLiteralFlags(flags) = self;
1526 match prefix {
1527 StringLiteralPrefix::Empty => Self(
1528 flags
1529 - StringLiteralFlagsInner::R_PREFIX_LOWER
1530 - StringLiteralFlagsInner::R_PREFIX_UPPER
1531 - StringLiteralFlagsInner::U_PREFIX,
1532 ),
1533 StringLiteralPrefix::Raw { uppercase: false } => Self(
1534 (flags | StringLiteralFlagsInner::R_PREFIX_LOWER)
1535 - StringLiteralFlagsInner::R_PREFIX_UPPER
1536 - StringLiteralFlagsInner::U_PREFIX,
1537 ),
1538 StringLiteralPrefix::Raw { uppercase: true } => Self(
1539 (flags | StringLiteralFlagsInner::R_PREFIX_UPPER)
1540 - StringLiteralFlagsInner::R_PREFIX_LOWER
1541 - StringLiteralFlagsInner::U_PREFIX,
1542 ),
1543 StringLiteralPrefix::Unicode => Self(
1544 (flags | StringLiteralFlagsInner::U_PREFIX)
1545 - StringLiteralFlagsInner::R_PREFIX_LOWER
1546 - StringLiteralFlagsInner::R_PREFIX_UPPER,
1547 ),
1548 }
1549 }
1550
1551 #[must_use]
1552 pub fn with_invalid(mut self) -> Self {
1553 self.0 |= StringLiteralFlagsInner::INVALID;
1554 self
1555 }
1556
1557 pub const fn prefix(self) -> StringLiteralPrefix {
1558 if self.0.contains(StringLiteralFlagsInner::U_PREFIX) {
1559 debug_assert!(
1560 !self.0.intersects(
1561 StringLiteralFlagsInner::R_PREFIX_LOWER
1562 .union(StringLiteralFlagsInner::R_PREFIX_UPPER)
1563 )
1564 );
1565 StringLiteralPrefix::Unicode
1566 } else if self.0.contains(StringLiteralFlagsInner::R_PREFIX_LOWER) {
1567 debug_assert!(!self.0.contains(StringLiteralFlagsInner::R_PREFIX_UPPER));
1568 StringLiteralPrefix::Raw { uppercase: false }
1569 } else if self.0.contains(StringLiteralFlagsInner::R_PREFIX_UPPER) {
1570 StringLiteralPrefix::Raw { uppercase: true }
1571 } else {
1572 StringLiteralPrefix::Empty
1573 }
1574 }
1575}
1576
1577impl StringFlags for StringLiteralFlags {
1578 fn quote_style(self) -> Quote {
1583 if self.0.contains(StringLiteralFlagsInner::DOUBLE) {
1584 Quote::Double
1585 } else {
1586 Quote::Single
1587 }
1588 }
1589
1590 fn triple_quotes(self) -> TripleQuotes {
1594 if self.0.contains(StringLiteralFlagsInner::TRIPLE_QUOTED) {
1595 TripleQuotes::Yes
1596 } else {
1597 TripleQuotes::No
1598 }
1599 }
1600
1601 fn prefix(self) -> AnyStringPrefix {
1602 AnyStringPrefix::Regular(self.prefix())
1603 }
1604
1605 fn is_unclosed(self) -> bool {
1606 self.0.intersects(StringLiteralFlagsInner::UNCLOSED)
1607 }
1608}
1609
1610impl fmt::Debug for StringLiteralFlags {
1611 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1612 f.debug_struct("StringLiteralFlags")
1613 .field("quote_style", &self.quote_style())
1614 .field("prefix", &self.prefix())
1615 .field("triple_quoted", &self.is_triple_quoted())
1616 .field("unclosed", &self.is_unclosed())
1617 .finish()
1618 }
1619}
1620
1621#[derive(Clone, Debug, PartialEq)]
1624#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1625pub struct StringLiteral {
1626 pub range: TextRange,
1627 pub node_index: AtomicNodeIndex,
1628 pub value: Box<str>,
1629 pub flags: StringLiteralFlags,
1630}
1631
1632impl Deref for StringLiteral {
1633 type Target = str;
1634
1635 fn deref(&self) -> &Self::Target {
1636 &self.value
1637 }
1638}
1639
1640impl StringLiteral {
1641 pub fn as_str(&self) -> &str {
1643 self
1644 }
1645
1646 pub fn invalid(range: TextRange) -> Self {
1648 Self {
1649 range,
1650 value: "".into(),
1651 node_index: AtomicNodeIndex::NONE,
1652 flags: StringLiteralFlags::empty().with_invalid(),
1653 }
1654 }
1655
1656 pub fn content_range(&self) -> TextRange {
1660 TextRange::new(
1661 self.start() + self.flags.opener_len(),
1662 self.end() - self.flags.closer_len(),
1663 )
1664 }
1665}
1666
1667impl From<StringLiteral> for Expr {
1668 fn from(payload: StringLiteral) -> Self {
1669 ExprStringLiteral {
1670 range: payload.range,
1671 node_index: AtomicNodeIndex::NONE,
1672 value: StringLiteralValue::single(payload),
1673 }
1674 .into()
1675 }
1676}
1677
1678#[derive(Clone)]
1681#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1682struct ConcatenatedStringLiteral {
1683 strings: Vec<StringLiteral>,
1685 value: OnceLock<Box<str>>,
1687}
1688
1689impl ConcatenatedStringLiteral {
1690 fn to_str(&self) -> &str {
1692 self.value.get_or_init(|| {
1693 let concatenated: String = self.strings.iter().map(StringLiteral::as_str).collect();
1694 concatenated.into_boxed_str()
1695 })
1696 }
1697}
1698
1699impl PartialEq for ConcatenatedStringLiteral {
1700 fn eq(&self, other: &Self) -> bool {
1701 if self.strings.len() != other.strings.len() {
1702 return false;
1703 }
1704 self.strings
1706 .iter()
1707 .zip(&other.strings)
1708 .all(|(s1, s2)| s1 == s2)
1709 }
1710}
1711
1712impl Debug for ConcatenatedStringLiteral {
1713 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1714 f.debug_struct("ConcatenatedStringLiteral")
1715 .field("strings", &self.strings)
1716 .field("value", &self.to_str())
1717 .finish()
1718 }
1719}
1720
1721impl ExprBytesLiteral {
1722 pub const fn as_single_part_bytestring(&self) -> Option<&BytesLiteral> {
1725 match &self.value.inner {
1726 BytesLiteralValueInner::Single(value) => Some(value),
1727 BytesLiteralValueInner::Concatenated(_) => None,
1728 }
1729 }
1730}
1731
1732#[derive(Clone, Debug, PartialEq)]
1734#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1735pub struct BytesLiteralValue {
1736 inner: BytesLiteralValueInner,
1737}
1738
1739impl BytesLiteralValue {
1740 pub fn single(value: BytesLiteral) -> Self {
1742 Self {
1743 inner: BytesLiteralValueInner::Single(value),
1744 }
1745 }
1746
1747 pub fn concatenated(values: Vec<BytesLiteral>) -> Self {
1755 assert!(
1756 values.len() > 1,
1757 "Use `BytesLiteralValue::single` to create single-part bytestrings"
1758 );
1759 Self {
1760 inner: BytesLiteralValueInner::Concatenated(values),
1761 }
1762 }
1763
1764 pub const fn is_implicit_concatenated(&self) -> bool {
1766 matches!(self.inner, BytesLiteralValueInner::Concatenated(_))
1767 }
1768
1769 pub fn as_slice(&self) -> &[BytesLiteral] {
1771 match &self.inner {
1772 BytesLiteralValueInner::Single(value) => std::slice::from_ref(value),
1773 BytesLiteralValueInner::Concatenated(value) => value.as_slice(),
1774 }
1775 }
1776
1777 fn as_mut_slice(&mut self) -> &mut [BytesLiteral] {
1779 match &mut self.inner {
1780 BytesLiteralValueInner::Single(value) => std::slice::from_mut(value),
1781 BytesLiteralValueInner::Concatenated(value) => value.as_mut_slice(),
1782 }
1783 }
1784
1785 pub fn iter(&self) -> Iter<'_, BytesLiteral> {
1787 self.as_slice().iter()
1788 }
1789
1790 pub fn iter_mut(&mut self) -> IterMut<'_, BytesLiteral> {
1793 self.as_mut_slice().iter_mut()
1794 }
1795
1796 pub fn is_empty(&self) -> bool {
1802 self.iter().all(|part| part.is_empty())
1803 }
1804
1805 pub fn len(&self) -> usize {
1807 self.iter().map(|part| part.len()).sum()
1808 }
1809
1810 pub fn bytes(&self) -> impl Iterator<Item = u8> + '_ {
1812 self.iter().flat_map(|part| part.as_slice().iter().copied())
1813 }
1814}
1815
1816impl<'a> IntoIterator for &'a BytesLiteralValue {
1817 type Item = &'a BytesLiteral;
1818 type IntoIter = Iter<'a, BytesLiteral>;
1819
1820 fn into_iter(self) -> Self::IntoIter {
1821 self.iter()
1822 }
1823}
1824
1825impl<'a> IntoIterator for &'a mut BytesLiteralValue {
1826 type Item = &'a mut BytesLiteral;
1827 type IntoIter = IterMut<'a, BytesLiteral>;
1828 fn into_iter(self) -> Self::IntoIter {
1829 self.iter_mut()
1830 }
1831}
1832
1833impl PartialEq<[u8]> for BytesLiteralValue {
1834 fn eq(&self, other: &[u8]) -> bool {
1835 if self.len() != other.len() {
1836 return false;
1837 }
1838 self.bytes()
1840 .zip(other.iter().copied())
1841 .all(|(b1, b2)| b1 == b2)
1842 }
1843}
1844
1845impl<'a> From<&'a BytesLiteralValue> for Cow<'a, [u8]> {
1846 fn from(value: &'a BytesLiteralValue) -> Self {
1847 match &value.inner {
1848 BytesLiteralValueInner::Single(BytesLiteral {
1849 value: bytes_value, ..
1850 }) => Cow::from(bytes_value.as_ref()),
1851 BytesLiteralValueInner::Concatenated(bytes_literal_vec) => Cow::Owned(
1852 bytes_literal_vec
1853 .iter()
1854 .flat_map(|bytes_literal| bytes_literal.value.to_vec())
1855 .collect::<Vec<u8>>(),
1856 ),
1857 }
1858 }
1859}
1860
1861#[derive(Clone, Debug, PartialEq)]
1863#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1864enum BytesLiteralValueInner {
1865 Single(BytesLiteral),
1867
1868 Concatenated(Vec<BytesLiteral>),
1870}
1871
1872bitflags! {
1873 #[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
1874 struct BytesLiteralFlagsInner: u8 {
1875 const DOUBLE = 1 << 0;
1878
1879 const TRIPLE_QUOTED = 1 << 1;
1882
1883 const R_PREFIX_LOWER = 1 << 2;
1886
1887 const R_PREFIX_UPPER = 1 << 3;
1892
1893 const INVALID = 1 << 4;
1895
1896 const UNCLOSED = 1 << 5;
1898 }
1899}
1900
1901#[cfg(feature = "get-size")]
1902impl get_size2::GetSize for BytesLiteralFlagsInner {}
1903
1904#[derive(Copy, Clone, Eq, PartialEq, Hash)]
1916#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
1917pub struct BytesLiteralFlags(BytesLiteralFlagsInner);
1918
1919impl BytesLiteralFlags {
1920 pub fn empty() -> Self {
1930 Self(BytesLiteralFlagsInner::empty())
1931 }
1932
1933 #[must_use]
1934 pub fn with_quote_style(mut self, quote_style: Quote) -> Self {
1935 self.0
1936 .set(BytesLiteralFlagsInner::DOUBLE, quote_style.is_double());
1937 self
1938 }
1939
1940 #[must_use]
1941 pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self {
1942 self.0.set(
1943 BytesLiteralFlagsInner::TRIPLE_QUOTED,
1944 triple_quotes.is_yes(),
1945 );
1946 self
1947 }
1948
1949 #[must_use]
1950 pub fn with_unclosed(mut self, unclosed: bool) -> Self {
1951 self.0.set(BytesLiteralFlagsInner::UNCLOSED, unclosed);
1952 self
1953 }
1954
1955 #[must_use]
1956 pub fn with_prefix(mut self, prefix: ByteStringPrefix) -> Self {
1957 match prefix {
1958 ByteStringPrefix::Regular => {
1959 self.0 -= BytesLiteralFlagsInner::R_PREFIX_LOWER;
1960 self.0 -= BytesLiteralFlagsInner::R_PREFIX_UPPER;
1961 }
1962 ByteStringPrefix::Raw { uppercase_r } => {
1963 self.0
1964 .set(BytesLiteralFlagsInner::R_PREFIX_UPPER, uppercase_r);
1965 self.0
1966 .set(BytesLiteralFlagsInner::R_PREFIX_LOWER, !uppercase_r);
1967 }
1968 }
1969 self
1970 }
1971
1972 #[must_use]
1973 pub fn with_invalid(mut self) -> Self {
1974 self.0 |= BytesLiteralFlagsInner::INVALID;
1975 self
1976 }
1977
1978 pub const fn prefix(self) -> ByteStringPrefix {
1979 if self.0.contains(BytesLiteralFlagsInner::R_PREFIX_LOWER) {
1980 debug_assert!(!self.0.contains(BytesLiteralFlagsInner::R_PREFIX_UPPER));
1981 ByteStringPrefix::Raw { uppercase_r: false }
1982 } else if self.0.contains(BytesLiteralFlagsInner::R_PREFIX_UPPER) {
1983 ByteStringPrefix::Raw { uppercase_r: true }
1984 } else {
1985 ByteStringPrefix::Regular
1986 }
1987 }
1988}
1989
1990impl StringFlags for BytesLiteralFlags {
1991 fn triple_quotes(self) -> TripleQuotes {
1995 if self.0.contains(BytesLiteralFlagsInner::TRIPLE_QUOTED) {
1996 TripleQuotes::Yes
1997 } else {
1998 TripleQuotes::No
1999 }
2000 }
2001
2002 fn quote_style(self) -> Quote {
2007 if self.0.contains(BytesLiteralFlagsInner::DOUBLE) {
2008 Quote::Double
2009 } else {
2010 Quote::Single
2011 }
2012 }
2013
2014 fn prefix(self) -> AnyStringPrefix {
2015 AnyStringPrefix::Bytes(self.prefix())
2016 }
2017
2018 fn is_unclosed(self) -> bool {
2019 self.0.intersects(BytesLiteralFlagsInner::UNCLOSED)
2020 }
2021}
2022
2023impl fmt::Debug for BytesLiteralFlags {
2024 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2025 f.debug_struct("BytesLiteralFlags")
2026 .field("quote_style", &self.quote_style())
2027 .field("prefix", &self.prefix())
2028 .field("triple_quoted", &self.is_triple_quoted())
2029 .field("unclosed", &self.is_unclosed())
2030 .finish()
2031 }
2032}
2033
2034#[derive(Clone, Debug, PartialEq)]
2037#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2038pub struct BytesLiteral {
2039 pub range: TextRange,
2040 pub node_index: AtomicNodeIndex,
2041 pub value: Box<[u8]>,
2042 pub flags: BytesLiteralFlags,
2043}
2044
2045impl Deref for BytesLiteral {
2046 type Target = [u8];
2047
2048 fn deref(&self) -> &Self::Target {
2049 &self.value
2050 }
2051}
2052
2053impl BytesLiteral {
2054 pub fn as_slice(&self) -> &[u8] {
2056 self
2057 }
2058
2059 pub fn invalid(range: TextRange) -> Self {
2061 Self {
2062 range,
2063 value: Box::new([]),
2064 node_index: AtomicNodeIndex::NONE,
2065 flags: BytesLiteralFlags::empty().with_invalid(),
2066 }
2067 }
2068}
2069
2070impl From<BytesLiteral> for Expr {
2071 fn from(payload: BytesLiteral) -> Self {
2072 ExprBytesLiteral {
2073 range: payload.range,
2074 node_index: AtomicNodeIndex::NONE,
2075 value: BytesLiteralValue::single(payload),
2076 }
2077 .into()
2078 }
2079}
2080
2081bitflags! {
2082 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
2091 struct AnyStringFlagsInner: u16 {
2092 const DOUBLE = 1 << 0;
2095
2096 const TRIPLE_QUOTED = 1 << 1;
2099
2100 const U_PREFIX = 1 << 2;
2104
2105 const B_PREFIX = 1 << 3;
2111
2112 const F_PREFIX = 1 << 4;
2116
2117 const T_PREFIX = 1 << 5;
2121
2122 const R_PREFIX_LOWER = 1 << 6;
2127
2128 const R_PREFIX_UPPER = 1 << 7;
2134
2135 const UNCLOSED = 1 << 8;
2137 }
2138}
2139
2140#[derive(Clone, Copy, PartialEq, Eq, Hash)]
2141pub struct AnyStringFlags(AnyStringFlagsInner);
2142
2143impl AnyStringFlags {
2144 #[must_use]
2145 pub fn with_prefix(mut self, prefix: AnyStringPrefix) -> Self {
2146 self.0 |= match prefix {
2147 AnyStringPrefix::Regular(StringLiteralPrefix::Empty) => AnyStringFlagsInner::empty(),
2149 AnyStringPrefix::Regular(StringLiteralPrefix::Unicode) => AnyStringFlagsInner::U_PREFIX,
2150 AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false }) => {
2151 AnyStringFlagsInner::R_PREFIX_LOWER
2152 }
2153 AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: true }) => {
2154 AnyStringFlagsInner::R_PREFIX_UPPER
2155 }
2156
2157 AnyStringPrefix::Bytes(ByteStringPrefix::Regular) => AnyStringFlagsInner::B_PREFIX,
2159 AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: false }) => {
2160 AnyStringFlagsInner::B_PREFIX.union(AnyStringFlagsInner::R_PREFIX_LOWER)
2161 }
2162 AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: true }) => {
2163 AnyStringFlagsInner::B_PREFIX.union(AnyStringFlagsInner::R_PREFIX_UPPER)
2164 }
2165
2166 AnyStringPrefix::Format(FStringPrefix::Regular) => AnyStringFlagsInner::F_PREFIX,
2168 AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: false }) => {
2169 AnyStringFlagsInner::F_PREFIX.union(AnyStringFlagsInner::R_PREFIX_LOWER)
2170 }
2171 AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: true }) => {
2172 AnyStringFlagsInner::F_PREFIX.union(AnyStringFlagsInner::R_PREFIX_UPPER)
2173 }
2174
2175 AnyStringPrefix::Template(TStringPrefix::Regular) => AnyStringFlagsInner::T_PREFIX,
2177 AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: false }) => {
2178 AnyStringFlagsInner::T_PREFIX.union(AnyStringFlagsInner::R_PREFIX_LOWER)
2179 }
2180 AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: true }) => {
2181 AnyStringFlagsInner::T_PREFIX.union(AnyStringFlagsInner::R_PREFIX_UPPER)
2182 }
2183 };
2184 self
2185 }
2186
2187 pub fn new(prefix: AnyStringPrefix, quotes: Quote, triple_quotes: TripleQuotes) -> Self {
2188 Self(AnyStringFlagsInner::empty())
2189 .with_prefix(prefix)
2190 .with_quote_style(quotes)
2191 .with_triple_quotes(triple_quotes)
2192 }
2193
2194 pub const fn is_u_string(self) -> bool {
2196 self.0.contains(AnyStringFlagsInner::U_PREFIX)
2197 }
2198
2199 pub const fn is_raw_string(self) -> bool {
2201 self.0.intersects(
2202 AnyStringFlagsInner::R_PREFIX_LOWER.union(AnyStringFlagsInner::R_PREFIX_UPPER),
2203 )
2204 }
2205
2206 pub const fn is_interpolated_string(self) -> bool {
2208 self.0
2209 .intersects(AnyStringFlagsInner::F_PREFIX.union(AnyStringFlagsInner::T_PREFIX))
2210 }
2211
2212 pub const fn is_byte_string(self) -> bool {
2214 self.0.contains(AnyStringFlagsInner::B_PREFIX)
2215 }
2216
2217 #[must_use]
2218 pub fn with_quote_style(mut self, quotes: Quote) -> Self {
2219 match quotes {
2220 Quote::Double => self.0 |= AnyStringFlagsInner::DOUBLE,
2221 Quote::Single => self.0 -= AnyStringFlagsInner::DOUBLE,
2222 }
2223 self
2224 }
2225
2226 #[must_use]
2227 pub fn with_triple_quotes(mut self, triple_quotes: TripleQuotes) -> Self {
2228 self.0
2229 .set(AnyStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes());
2230 self
2231 }
2232
2233 #[must_use]
2234 pub fn with_unclosed(mut self, unclosed: bool) -> Self {
2235 self.0.set(AnyStringFlagsInner::UNCLOSED, unclosed);
2236 self
2237 }
2238}
2239
2240impl StringFlags for AnyStringFlags {
2241 fn quote_style(self) -> Quote {
2243 if self.0.contains(AnyStringFlagsInner::DOUBLE) {
2244 Quote::Double
2245 } else {
2246 Quote::Single
2247 }
2248 }
2249
2250 fn triple_quotes(self) -> TripleQuotes {
2251 if self.0.contains(AnyStringFlagsInner::TRIPLE_QUOTED) {
2252 TripleQuotes::Yes
2253 } else {
2254 TripleQuotes::No
2255 }
2256 }
2257
2258 fn prefix(self) -> AnyStringPrefix {
2259 let AnyStringFlags(flags) = self;
2260
2261 if flags.contains(AnyStringFlagsInner::F_PREFIX) {
2263 if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) {
2264 return AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: false });
2265 }
2266 if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) {
2267 return AnyStringPrefix::Format(FStringPrefix::Raw { uppercase_r: true });
2268 }
2269 return AnyStringPrefix::Format(FStringPrefix::Regular);
2270 }
2271
2272 if flags.contains(AnyStringFlagsInner::T_PREFIX) {
2274 if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) {
2275 return AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: false });
2276 }
2277 if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) {
2278 return AnyStringPrefix::Template(TStringPrefix::Raw { uppercase_r: true });
2279 }
2280 return AnyStringPrefix::Template(TStringPrefix::Regular);
2281 }
2282
2283 if flags.contains(AnyStringFlagsInner::B_PREFIX) {
2285 if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) {
2286 return AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: false });
2287 }
2288 if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) {
2289 return AnyStringPrefix::Bytes(ByteStringPrefix::Raw { uppercase_r: true });
2290 }
2291 return AnyStringPrefix::Bytes(ByteStringPrefix::Regular);
2292 }
2293
2294 if flags.contains(AnyStringFlagsInner::R_PREFIX_LOWER) {
2296 return AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false });
2297 }
2298 if flags.contains(AnyStringFlagsInner::R_PREFIX_UPPER) {
2299 return AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: true });
2300 }
2301 if flags.contains(AnyStringFlagsInner::U_PREFIX) {
2302 return AnyStringPrefix::Regular(StringLiteralPrefix::Unicode);
2303 }
2304 AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
2305 }
2306
2307 fn is_unclosed(self) -> bool {
2308 self.0.intersects(AnyStringFlagsInner::UNCLOSED)
2309 }
2310}
2311
2312impl fmt::Debug for AnyStringFlags {
2313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2314 f.debug_struct("AnyStringFlags")
2315 .field("prefix", &self.prefix())
2316 .field("triple_quoted", &self.is_triple_quoted())
2317 .field("quote_style", &self.quote_style())
2318 .field("unclosed", &self.is_unclosed())
2319 .finish()
2320 }
2321}
2322
2323impl From<AnyStringFlags> for StringLiteralFlags {
2324 fn from(value: AnyStringFlags) -> StringLiteralFlags {
2325 let AnyStringPrefix::Regular(prefix) = value.prefix() else {
2326 unreachable!(
2327 "Should never attempt to convert {} into a regular string",
2328 value.prefix()
2329 )
2330 };
2331 StringLiteralFlags::empty()
2332 .with_quote_style(value.quote_style())
2333 .with_prefix(prefix)
2334 .with_triple_quotes(value.triple_quotes())
2335 .with_unclosed(value.is_unclosed())
2336 }
2337}
2338
2339impl From<StringLiteralFlags> for AnyStringFlags {
2340 fn from(value: StringLiteralFlags) -> Self {
2341 value.as_any_string_flags()
2342 }
2343}
2344
2345impl From<AnyStringFlags> for BytesLiteralFlags {
2346 fn from(value: AnyStringFlags) -> BytesLiteralFlags {
2347 let AnyStringPrefix::Bytes(bytestring_prefix) = value.prefix() else {
2348 unreachable!(
2349 "Should never attempt to convert {} into a bytestring",
2350 value.prefix()
2351 )
2352 };
2353 BytesLiteralFlags::empty()
2354 .with_quote_style(value.quote_style())
2355 .with_prefix(bytestring_prefix)
2356 .with_triple_quotes(value.triple_quotes())
2357 .with_unclosed(value.is_unclosed())
2358 }
2359}
2360
2361impl From<BytesLiteralFlags> for AnyStringFlags {
2362 fn from(value: BytesLiteralFlags) -> Self {
2363 value.as_any_string_flags()
2364 }
2365}
2366
2367impl From<AnyStringFlags> for FStringFlags {
2368 fn from(value: AnyStringFlags) -> FStringFlags {
2369 let AnyStringPrefix::Format(prefix) = value.prefix() else {
2370 unreachable!(
2371 "Should never attempt to convert {} into an f-string",
2372 value.prefix()
2373 )
2374 };
2375 FStringFlags::empty()
2376 .with_quote_style(value.quote_style())
2377 .with_prefix(prefix)
2378 .with_triple_quotes(value.triple_quotes())
2379 .with_unclosed(value.is_unclosed())
2380 }
2381}
2382
2383impl From<FStringFlags> for AnyStringFlags {
2384 fn from(value: FStringFlags) -> Self {
2385 value.as_any_string_flags()
2386 }
2387}
2388
2389impl From<AnyStringFlags> for TStringFlags {
2390 fn from(value: AnyStringFlags) -> TStringFlags {
2391 let AnyStringPrefix::Template(prefix) = value.prefix() else {
2392 unreachable!(
2393 "Should never attempt to convert {} into a t-string",
2394 value.prefix()
2395 )
2396 };
2397 TStringFlags::empty()
2398 .with_quote_style(value.quote_style())
2399 .with_prefix(prefix)
2400 .with_triple_quotes(value.triple_quotes())
2401 .with_unclosed(value.is_unclosed())
2402 }
2403}
2404
2405impl From<TStringFlags> for AnyStringFlags {
2406 fn from(value: TStringFlags) -> Self {
2407 value.as_any_string_flags()
2408 }
2409}
2410
2411#[derive(Clone, Debug, PartialEq, is_macro::Is)]
2412#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2413pub enum Number {
2414 Int(int::Int),
2415 Float(f64),
2416 Complex { real: f64, imag: f64 },
2417}
2418
2419impl ExprName {
2420 pub fn id(&self) -> &Name {
2421 &self.id
2422 }
2423
2424 pub const fn is_invalid(&self) -> bool {
2428 matches!(self.ctx, ExprContext::Invalid)
2429 }
2430}
2431
2432impl ExprList {
2433 pub fn iter(&self) -> std::slice::Iter<'_, Expr> {
2434 self.elts.iter()
2435 }
2436
2437 pub fn len(&self) -> usize {
2438 self.elts.len()
2439 }
2440
2441 pub fn is_empty(&self) -> bool {
2442 self.elts.is_empty()
2443 }
2444}
2445
2446impl<'a> IntoIterator for &'a ExprList {
2447 type IntoIter = std::slice::Iter<'a, Expr>;
2448 type Item = &'a Expr;
2449
2450 fn into_iter(self) -> Self::IntoIter {
2451 self.iter()
2452 }
2453}
2454
2455impl ExprTuple {
2456 pub fn iter(&self) -> std::slice::Iter<'_, Expr> {
2457 self.elts.iter()
2458 }
2459
2460 pub fn len(&self) -> usize {
2461 self.elts.len()
2462 }
2463
2464 pub fn is_empty(&self) -> bool {
2465 self.elts.is_empty()
2466 }
2467}
2468
2469impl<'a> IntoIterator for &'a ExprTuple {
2470 type IntoIter = std::slice::Iter<'a, Expr>;
2471 type Item = &'a Expr;
2472
2473 fn into_iter(self) -> Self::IntoIter {
2474 self.iter()
2475 }
2476}
2477
2478#[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)]
2480#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2481pub enum ExprContext {
2482 Load,
2483 Store,
2484 Del,
2485 Invalid,
2486}
2487
2488#[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)]
2490#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2491pub enum BoolOp {
2492 And,
2493 Or,
2494}
2495
2496impl BoolOp {
2497 pub const fn as_str(&self) -> &'static str {
2498 match self {
2499 BoolOp::And => "and",
2500 BoolOp::Or => "or",
2501 }
2502 }
2503}
2504
2505impl fmt::Display for BoolOp {
2506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2507 f.write_str(self.as_str())
2508 }
2509}
2510
2511#[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)]
2513#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2514pub enum Operator {
2515 Add,
2516 Sub,
2517 Mult,
2518 MatMult,
2519 Div,
2520 Mod,
2521 Pow,
2522 LShift,
2523 RShift,
2524 BitOr,
2525 BitXor,
2526 BitAnd,
2527 FloorDiv,
2528}
2529
2530impl Operator {
2531 pub const fn as_str(&self) -> &'static str {
2532 match self {
2533 Operator::Add => "+",
2534 Operator::Sub => "-",
2535 Operator::Mult => "*",
2536 Operator::MatMult => "@",
2537 Operator::Div => "/",
2538 Operator::Mod => "%",
2539 Operator::Pow => "**",
2540 Operator::LShift => "<<",
2541 Operator::RShift => ">>",
2542 Operator::BitOr => "|",
2543 Operator::BitXor => "^",
2544 Operator::BitAnd => "&",
2545 Operator::FloorDiv => "//",
2546 }
2547 }
2548
2549 pub const fn dunder(self) -> &'static str {
2551 match self {
2552 Operator::Add => "__add__",
2553 Operator::Sub => "__sub__",
2554 Operator::Mult => "__mul__",
2555 Operator::MatMult => "__matmul__",
2556 Operator::Div => "__truediv__",
2557 Operator::Mod => "__mod__",
2558 Operator::Pow => "__pow__",
2559 Operator::LShift => "__lshift__",
2560 Operator::RShift => "__rshift__",
2561 Operator::BitOr => "__or__",
2562 Operator::BitXor => "__xor__",
2563 Operator::BitAnd => "__and__",
2564 Operator::FloorDiv => "__floordiv__",
2565 }
2566 }
2567
2568 pub const fn in_place_dunder(self) -> &'static str {
2570 match self {
2571 Operator::Add => "__iadd__",
2572 Operator::Sub => "__isub__",
2573 Operator::Mult => "__imul__",
2574 Operator::MatMult => "__imatmul__",
2575 Operator::Div => "__itruediv__",
2576 Operator::Mod => "__imod__",
2577 Operator::Pow => "__ipow__",
2578 Operator::LShift => "__ilshift__",
2579 Operator::RShift => "__irshift__",
2580 Operator::BitOr => "__ior__",
2581 Operator::BitXor => "__ixor__",
2582 Operator::BitAnd => "__iand__",
2583 Operator::FloorDiv => "__ifloordiv__",
2584 }
2585 }
2586
2587 pub const fn reflected_dunder(self) -> &'static str {
2589 match self {
2590 Operator::Add => "__radd__",
2591 Operator::Sub => "__rsub__",
2592 Operator::Mult => "__rmul__",
2593 Operator::MatMult => "__rmatmul__",
2594 Operator::Div => "__rtruediv__",
2595 Operator::Mod => "__rmod__",
2596 Operator::Pow => "__rpow__",
2597 Operator::LShift => "__rlshift__",
2598 Operator::RShift => "__rrshift__",
2599 Operator::BitOr => "__ror__",
2600 Operator::BitXor => "__rxor__",
2601 Operator::BitAnd => "__rand__",
2602 Operator::FloorDiv => "__rfloordiv__",
2603 }
2604 }
2605}
2606
2607impl fmt::Display for Operator {
2608 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2609 f.write_str(self.as_str())
2610 }
2611}
2612
2613#[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)]
2615#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2616pub enum UnaryOp {
2617 Invert,
2618 Not,
2619 UAdd,
2620 USub,
2621}
2622
2623impl UnaryOp {
2624 pub const fn as_str(&self) -> &'static str {
2625 match self {
2626 UnaryOp::Invert => "~",
2627 UnaryOp::Not => "not",
2628 UnaryOp::UAdd => "+",
2629 UnaryOp::USub => "-",
2630 }
2631 }
2632}
2633
2634impl fmt::Display for UnaryOp {
2635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2636 f.write_str(self.as_str())
2637 }
2638}
2639
2640#[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)]
2642#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2643pub enum CmpOp {
2644 Eq,
2645 NotEq,
2646 Lt,
2647 LtE,
2648 Gt,
2649 GtE,
2650 Is,
2651 IsNot,
2652 In,
2653 NotIn,
2654}
2655
2656impl CmpOp {
2657 pub const fn as_str(&self) -> &'static str {
2658 match self {
2659 CmpOp::Eq => "==",
2660 CmpOp::NotEq => "!=",
2661 CmpOp::Lt => "<",
2662 CmpOp::LtE => "<=",
2663 CmpOp::Gt => ">",
2664 CmpOp::GtE => ">=",
2665 CmpOp::Is => "is",
2666 CmpOp::IsNot => "is not",
2667 CmpOp::In => "in",
2668 CmpOp::NotIn => "not in",
2669 }
2670 }
2671
2672 #[must_use]
2673 pub const fn negate(&self) -> Self {
2674 match self {
2675 CmpOp::Eq => CmpOp::NotEq,
2676 CmpOp::NotEq => CmpOp::Eq,
2677 CmpOp::Lt => CmpOp::GtE,
2678 CmpOp::LtE => CmpOp::Gt,
2679 CmpOp::Gt => CmpOp::LtE,
2680 CmpOp::GtE => CmpOp::Lt,
2681 CmpOp::Is => CmpOp::IsNot,
2682 CmpOp::IsNot => CmpOp::Is,
2683 CmpOp::In => CmpOp::NotIn,
2684 CmpOp::NotIn => CmpOp::In,
2685 }
2686 }
2687}
2688
2689impl fmt::Display for CmpOp {
2690 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2691 f.write_str(self.as_str())
2692 }
2693}
2694
2695#[derive(Clone, Debug, PartialEq)]
2697#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2698pub struct Comprehension {
2699 pub range: TextRange,
2700 pub node_index: AtomicNodeIndex,
2701 pub target: Expr,
2702 pub iter: Expr,
2703 pub ifs: Vec<Expr>,
2704 pub is_async: bool,
2705}
2706
2707#[derive(Clone, Debug, PartialEq)]
2709#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2710pub struct ExceptHandlerExceptHandler {
2711 pub range: TextRange,
2712 pub node_index: AtomicNodeIndex,
2713 pub type_: Option<Box<Expr>>,
2714 pub name: Option<Identifier>,
2715 pub body: Vec<Stmt>,
2716}
2717
2718#[derive(Clone, Debug, PartialEq)]
2720#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2721pub struct Parameter {
2722 pub range: TextRange,
2723 pub node_index: AtomicNodeIndex,
2724 pub name: Identifier,
2725 pub annotation: Option<Box<Expr>>,
2726}
2727
2728impl Parameter {
2729 pub const fn name(&self) -> &Identifier {
2730 &self.name
2731 }
2732
2733 pub fn annotation(&self) -> Option<&Expr> {
2734 self.annotation.as_deref()
2735 }
2736}
2737
2738#[derive(Clone, Debug, PartialEq)]
2740#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2741pub struct Keyword {
2742 pub range: TextRange,
2743 pub node_index: AtomicNodeIndex,
2744 pub arg: Option<Identifier>,
2745 pub value: Expr,
2746}
2747
2748#[derive(Clone, Debug, PartialEq)]
2750#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2751pub struct Alias {
2752 pub range: TextRange,
2753 pub node_index: AtomicNodeIndex,
2754 pub name: Identifier,
2755 pub asname: Option<Identifier>,
2756}
2757
2758#[derive(Clone, Debug, PartialEq)]
2760#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2761pub struct WithItem {
2762 pub range: TextRange,
2763 pub node_index: AtomicNodeIndex,
2764 pub context_expr: Expr,
2765 pub optional_vars: Option<Box<Expr>>,
2766}
2767
2768#[derive(Clone, Debug, PartialEq)]
2770#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2771pub struct MatchCase {
2772 pub range: TextRange,
2773 pub node_index: AtomicNodeIndex,
2774 pub pattern: Pattern,
2775 pub guard: Option<Box<Expr>>,
2776 pub body: Vec<Stmt>,
2777}
2778
2779impl Pattern {
2780 pub fn is_irrefutable(&self) -> bool {
2784 self.irrefutable_pattern().is_some()
2785 }
2786
2787 pub fn irrefutable_pattern(&self) -> Option<IrrefutablePattern> {
2789 match self {
2790 Pattern::MatchAs(PatternMatchAs {
2791 pattern,
2792 name,
2793 range,
2794 node_index,
2795 }) => match pattern {
2796 Some(pattern) => pattern.irrefutable_pattern(),
2797 None => match name {
2798 Some(name) => Some(IrrefutablePattern {
2799 kind: IrrefutablePatternKind::Name(name.id.clone()),
2800 range: *range,
2801 node_index: node_index.clone(),
2802 }),
2803 None => Some(IrrefutablePattern {
2804 kind: IrrefutablePatternKind::Wildcard,
2805 range: *range,
2806 node_index: node_index.clone(),
2807 }),
2808 },
2809 },
2810 Pattern::MatchOr(PatternMatchOr { patterns, .. }) => {
2811 patterns.iter().find_map(Pattern::irrefutable_pattern)
2812 }
2813 _ => None,
2814 }
2815 }
2816
2817 pub fn is_wildcard(&self) -> bool {
2829 match self {
2830 Pattern::MatchAs(PatternMatchAs { pattern, .. }) => {
2831 pattern.as_deref().is_none_or(Pattern::is_wildcard)
2832 }
2833 Pattern::MatchOr(PatternMatchOr { patterns, .. }) => {
2834 patterns.iter().all(Pattern::is_wildcard)
2835 }
2836 _ => false,
2837 }
2838 }
2839}
2840
2841pub struct IrrefutablePattern {
2842 pub kind: IrrefutablePatternKind,
2843 pub range: TextRange,
2844 pub node_index: AtomicNodeIndex,
2845}
2846
2847#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2848#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2849pub enum IrrefutablePatternKind {
2850 Name(Name),
2851 Wildcard,
2852}
2853
2854#[derive(Clone, Debug, PartialEq)]
2859#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2860pub struct PatternArguments {
2861 pub range: TextRange,
2862 pub node_index: AtomicNodeIndex,
2863 pub patterns: Vec<Pattern>,
2864 pub keywords: Vec<PatternKeyword>,
2865}
2866
2867#[derive(Clone, Debug, PartialEq)]
2872#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2873pub struct PatternKeyword {
2874 pub range: TextRange,
2875 pub node_index: AtomicNodeIndex,
2876 pub attr: Identifier,
2877 pub pattern: Pattern,
2878}
2879
2880impl PatternArguments {
2881 pub fn patterns_source_order(&self) -> PatternArgumentsSourceOrder<'_> {
2883 PatternArgumentsSourceOrder {
2884 patterns: &self.patterns,
2885 keywords: &self.keywords,
2886 next_pattern: 0,
2887 next_keyword: 0,
2888 }
2889 }
2890}
2891
2892#[derive(Clone)]
2894pub struct PatternArgumentsSourceOrder<'a> {
2895 patterns: &'a [Pattern],
2896 keywords: &'a [PatternKeyword],
2897 next_pattern: usize,
2898 next_keyword: usize,
2899}
2900
2901#[derive(Copy, Clone, Debug, PartialEq)]
2903pub enum PatternOrKeyword<'a> {
2904 Pattern(&'a Pattern),
2905 Keyword(&'a PatternKeyword),
2906}
2907
2908impl<'a> Iterator for PatternArgumentsSourceOrder<'a> {
2909 type Item = PatternOrKeyword<'a>;
2910
2911 fn next(&mut self) -> Option<Self::Item> {
2912 let pattern = self.patterns.get(self.next_pattern);
2913 let keyword = self.keywords.get(self.next_keyword);
2914
2915 if let Some(pattern) = pattern
2916 && keyword.is_none_or(|keyword| pattern.start() <= keyword.start())
2917 {
2918 self.next_pattern += 1;
2919 Some(PatternOrKeyword::Pattern(pattern))
2920 } else if let Some(keyword) = keyword {
2921 self.next_keyword += 1;
2922 Some(PatternOrKeyword::Keyword(keyword))
2923 } else {
2924 None
2925 }
2926 }
2927}
2928
2929impl FusedIterator for PatternArgumentsSourceOrder<'_> {}
2930
2931impl TypeParam {
2932 pub const fn name(&self) -> &Identifier {
2933 match self {
2934 Self::TypeVar(x) => &x.name,
2935 Self::ParamSpec(x) => &x.name,
2936 Self::TypeVarTuple(x) => &x.name,
2937 }
2938 }
2939
2940 pub fn default(&self) -> Option<&Expr> {
2941 match self {
2942 Self::TypeVar(x) => x.default.as_deref(),
2943 Self::ParamSpec(x) => x.default.as_deref(),
2944 Self::TypeVarTuple(x) => x.default.as_deref(),
2945 }
2946 }
2947}
2948
2949#[derive(Clone, Debug, PartialEq)]
2951#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
2952pub struct Decorator {
2953 pub range: TextRange,
2954 pub node_index: AtomicNodeIndex,
2955 pub expression: Expr,
2956}
2957
2958#[derive(Debug, PartialEq, Clone, Copy)]
2960pub enum AnyParameterRef<'a> {
2961 Variadic(&'a Parameter),
2968
2969 NonVariadic(&'a ParameterWithDefault),
2976}
2977
2978impl<'a> AnyParameterRef<'a> {
2979 pub const fn as_parameter(self) -> &'a Parameter {
2980 match self {
2981 Self::NonVariadic(param) => ¶m.parameter,
2982 Self::Variadic(param) => param,
2983 }
2984 }
2985
2986 pub const fn name(self) -> &'a Identifier {
2987 &self.as_parameter().name
2988 }
2989
2990 pub const fn is_variadic(self) -> bool {
2991 matches!(self, Self::Variadic(_))
2992 }
2993
2994 pub fn annotation(self) -> Option<&'a Expr> {
2995 self.as_parameter().annotation.as_deref()
2996 }
2997
2998 pub fn default(self) -> Option<&'a Expr> {
2999 match self {
3000 Self::NonVariadic(param) => param.default.as_deref(),
3001 Self::Variadic(_) => None,
3002 }
3003 }
3004}
3005
3006impl Ranged for AnyParameterRef<'_> {
3007 fn range(&self) -> TextRange {
3008 match self {
3009 Self::NonVariadic(param) => param.range,
3010 Self::Variadic(param) => param.range,
3011 }
3012 }
3013}
3014
3015#[derive(Clone, Debug, PartialEq, Default)]
3026#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3027pub struct Parameters {
3028 pub range: TextRange,
3029 pub node_index: AtomicNodeIndex,
3030 pub posonlyargs: Vec<ParameterWithDefault>,
3031 pub args: Vec<ParameterWithDefault>,
3032 pub vararg: Option<Box<Parameter>>,
3033 pub kwonlyargs: Vec<ParameterWithDefault>,
3034 pub kwarg: Option<Box<Parameter>>,
3035}
3036
3037impl Parameters {
3038 pub fn iter_non_variadic_params(&self) -> impl Iterator<Item = &ParameterWithDefault> {
3043 self.posonlyargs
3044 .iter()
3045 .chain(&self.args)
3046 .chain(&self.kwonlyargs)
3047 }
3048
3049 pub fn find(&self, name: &str) -> Option<&ParameterWithDefault> {
3051 self.iter_non_variadic_params()
3052 .find(|arg| arg.parameter.name.as_str() == name)
3053 }
3054
3055 pub fn index(&self, name: &str) -> Option<usize> {
3057 self.iter_non_variadic_params()
3058 .position(|arg| arg.parameter.name.as_str() == name)
3059 }
3060
3061 pub fn iter(&self) -> ParametersIterator<'_> {
3063 ParametersIterator::new(self)
3064 }
3065
3066 pub fn len(&self) -> usize {
3068 let Parameters {
3069 range: _,
3070 node_index: _,
3071 posonlyargs,
3072 args,
3073 vararg,
3074 kwonlyargs,
3075 kwarg,
3076 } = self;
3077 posonlyargs
3084 .len()
3085 .checked_add(args.len())
3086 .and_then(|length| length.checked_add(usize::from(vararg.is_some())))
3087 .and_then(|length| length.checked_add(kwonlyargs.len()))
3088 .and_then(|length| length.checked_add(usize::from(kwarg.is_some())))
3089 .expect("Failed to fit the number of parameters into a usize")
3090 }
3091
3092 pub fn includes(&self, name: &str) -> bool {
3094 self.iter().any(|param| param.name() == name)
3095 }
3096
3097 pub fn is_empty(&self) -> bool {
3099 self.posonlyargs.is_empty()
3100 && self.args.is_empty()
3101 && self.kwonlyargs.is_empty()
3102 && self.vararg.is_none()
3103 && self.kwarg.is_none()
3104 }
3105
3106 pub fn iter_source_order(&self) -> ParametersSourceOrderIterator<'_> {
3114 let mut variadics = [self.vararg.as_deref(), self.kwarg.as_deref()];
3115 variadics.sort_by_key(|param| param.map_or(TextSize::new(u32::MAX), Ranged::start));
3116
3117 ParametersSourceOrderIterator {
3118 next_non_variadic_peeked: None,
3119 posonlyargs: self.posonlyargs.iter(),
3120 args: self.args.iter(),
3121 kwonlyargs: self.kwonlyargs.iter(),
3122 variadics,
3123 next_variadic: 0,
3124 }
3125 }
3126}
3127
3128pub struct ParametersIterator<'a> {
3129 posonlyargs: Iter<'a, ParameterWithDefault>,
3130 args: Iter<'a, ParameterWithDefault>,
3131 vararg: Option<&'a Parameter>,
3132 kwonlyargs: Iter<'a, ParameterWithDefault>,
3133 kwarg: Option<&'a Parameter>,
3134}
3135
3136impl<'a> ParametersIterator<'a> {
3137 fn new(parameters: &'a Parameters) -> Self {
3138 let Parameters {
3139 range: _,
3140 node_index: _,
3141 posonlyargs,
3142 args,
3143 vararg,
3144 kwonlyargs,
3145 kwarg,
3146 } = parameters;
3147 Self {
3148 posonlyargs: posonlyargs.iter(),
3149 args: args.iter(),
3150 vararg: vararg.as_deref(),
3151 kwonlyargs: kwonlyargs.iter(),
3152 kwarg: kwarg.as_deref(),
3153 }
3154 }
3155}
3156
3157impl<'a> Iterator for ParametersIterator<'a> {
3158 type Item = AnyParameterRef<'a>;
3159
3160 fn next(&mut self) -> Option<Self::Item> {
3161 let ParametersIterator {
3162 posonlyargs,
3163 args,
3164 vararg,
3165 kwonlyargs,
3166 kwarg,
3167 } = self;
3168
3169 if let Some(param) = posonlyargs.next() {
3170 return Some(AnyParameterRef::NonVariadic(param));
3171 }
3172 if let Some(param) = args.next() {
3173 return Some(AnyParameterRef::NonVariadic(param));
3174 }
3175 if let Some(param) = vararg.take() {
3176 return Some(AnyParameterRef::Variadic(param));
3177 }
3178 if let Some(param) = kwonlyargs.next() {
3179 return Some(AnyParameterRef::NonVariadic(param));
3180 }
3181 kwarg.take().map(AnyParameterRef::Variadic)
3182 }
3183
3184 fn size_hint(&self) -> (usize, Option<usize>) {
3185 let ParametersIterator {
3186 posonlyargs,
3187 args,
3188 vararg,
3189 kwonlyargs,
3190 kwarg,
3191 } = self;
3192
3193 let posonlyargs_len = posonlyargs.len();
3194 let args_len = args.len();
3195 let vararg_len = usize::from(vararg.is_some());
3196 let kwonlyargs_len = kwonlyargs.len();
3197 let kwarg_len = usize::from(kwarg.is_some());
3198
3199 let lower = posonlyargs_len
3200 .saturating_add(args_len)
3201 .saturating_add(vararg_len)
3202 .saturating_add(kwonlyargs_len)
3203 .saturating_add(kwarg_len);
3204
3205 let upper = posonlyargs_len
3206 .checked_add(args_len)
3207 .and_then(|length| length.checked_add(vararg_len))
3208 .and_then(|length| length.checked_add(kwonlyargs_len))
3209 .and_then(|length| length.checked_add(kwarg_len));
3210
3211 (lower, upper)
3212 }
3213
3214 fn last(mut self) -> Option<Self::Item> {
3215 self.next_back()
3216 }
3217}
3218
3219impl DoubleEndedIterator for ParametersIterator<'_> {
3220 fn next_back(&mut self) -> Option<Self::Item> {
3221 let ParametersIterator {
3222 posonlyargs,
3223 args,
3224 vararg,
3225 kwonlyargs,
3226 kwarg,
3227 } = self;
3228
3229 if let Some(param) = kwarg.take() {
3230 return Some(AnyParameterRef::Variadic(param));
3231 }
3232 if let Some(param) = kwonlyargs.next_back() {
3233 return Some(AnyParameterRef::NonVariadic(param));
3234 }
3235 if let Some(param) = vararg.take() {
3236 return Some(AnyParameterRef::Variadic(param));
3237 }
3238 if let Some(param) = args.next_back() {
3239 return Some(AnyParameterRef::NonVariadic(param));
3240 }
3241 posonlyargs.next_back().map(AnyParameterRef::NonVariadic)
3242 }
3243}
3244
3245impl FusedIterator for ParametersIterator<'_> {}
3246
3247impl ExactSizeIterator for ParametersIterator<'_> {}
3250
3251impl<'a> IntoIterator for &'a Parameters {
3252 type IntoIter = ParametersIterator<'a>;
3253 type Item = AnyParameterRef<'a>;
3254 fn into_iter(self) -> Self::IntoIter {
3255 self.iter()
3256 }
3257}
3258
3259impl<'a> IntoIterator for &'a Box<Parameters> {
3260 type IntoIter = ParametersIterator<'a>;
3261 type Item = AnyParameterRef<'a>;
3262 fn into_iter(self) -> Self::IntoIter {
3263 (&**self).into_iter()
3264 }
3265}
3266
3267pub struct ParametersSourceOrderIterator<'a> {
3269 next_non_variadic_peeked: Option<&'a ParameterWithDefault>,
3270 posonlyargs: Iter<'a, ParameterWithDefault>,
3271 args: Iter<'a, ParameterWithDefault>,
3272 kwonlyargs: Iter<'a, ParameterWithDefault>,
3273 variadics: [Option<&'a Parameter>; 2],
3274 next_variadic: usize,
3275}
3276
3277impl<'a> ParametersSourceOrderIterator<'a> {
3278 fn next_variadic_before(&mut self, before: TextSize) -> Option<&'a Parameter> {
3280 let param = self.variadics.get(self.next_variadic).copied().flatten()?;
3281 if param.start() < before {
3282 self.next_variadic += 1;
3283 Some(param)
3284 } else {
3285 None
3286 }
3287 }
3288
3289 fn next_non_variadic(&mut self) -> Option<&'a ParameterWithDefault> {
3290 self.next_non_variadic_peeked
3291 .take()
3292 .or_else(|| self.posonlyargs.next())
3293 .or_else(|| self.args.next())
3294 .or_else(|| self.kwonlyargs.next())
3295 }
3296
3297 fn peek_next_non_variadic(&mut self) -> Option<&'a ParameterWithDefault> {
3298 let next = self.next_non_variadic()?;
3299 self.next_non_variadic_peeked = Some(next);
3300 Some(next)
3301 }
3302}
3303
3304impl<'a> Iterator for ParametersSourceOrderIterator<'a> {
3305 type Item = AnyParameterRef<'a>;
3306
3307 fn next(&mut self) -> Option<Self::Item> {
3308 let next_non_variadic_start = self
3311 .peek_next_non_variadic()
3312 .map_or(TextSize::new(u32::MAX), Ranged::start);
3313
3314 if let Some(variadic) = self.next_variadic_before(next_non_variadic_start) {
3315 return Some(AnyParameterRef::Variadic(variadic));
3316 }
3317
3318 if let Some(non_variadic) = self.next_non_variadic() {
3319 return Some(AnyParameterRef::NonVariadic(non_variadic));
3320 }
3321
3322 self.next_variadic_before(TextSize::new(u32::MAX))
3324 .map(AnyParameterRef::Variadic)
3325 }
3326}
3327
3328impl FusedIterator for ParametersSourceOrderIterator<'_> {}
3329
3330#[derive(Clone, Debug, PartialEq)]
3335#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3336pub struct ParameterWithDefault {
3337 pub range: TextRange,
3338 pub node_index: AtomicNodeIndex,
3339 pub parameter: Parameter,
3340 pub default: Option<Box<Expr>>,
3341}
3342
3343impl ParameterWithDefault {
3344 pub fn default(&self) -> Option<&Expr> {
3345 self.default.as_deref()
3346 }
3347
3348 pub const fn name(&self) -> &Identifier {
3349 self.parameter.name()
3350 }
3351
3352 pub fn annotation(&self) -> Option<&Expr> {
3353 self.parameter.annotation()
3354 }
3355
3356 pub fn uses_pep_484_positional_only_convention(&self) -> bool {
3360 let name = self.name();
3361 name.starts_with("__") && !name.ends_with("__")
3362 }
3363}
3364
3365#[derive(Clone, Debug, PartialEq)]
3388#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3389pub struct Arguments {
3390 pub range: TextRange,
3391 pub node_index: AtomicNodeIndex,
3392 pub args: Box<[Expr]>,
3393 pub keywords: Box<[Keyword]>,
3394}
3395
3396#[derive(Copy, Clone, Debug, PartialEq)]
3398pub enum ArgOrKeyword<'a> {
3399 Arg(&'a Expr),
3400 Keyword(&'a Keyword),
3401}
3402
3403impl<'a> ArgOrKeyword<'a> {
3404 pub const fn value(self) -> &'a Expr {
3405 match self {
3406 ArgOrKeyword::Arg(argument) => argument,
3407 ArgOrKeyword::Keyword(keyword) => &keyword.value,
3408 }
3409 }
3410
3411 pub const fn is_variadic(self) -> bool {
3412 match self {
3413 ArgOrKeyword::Arg(expr) => expr.is_starred_expr(),
3414 ArgOrKeyword::Keyword(keyword) => keyword.arg.is_none(),
3415 }
3416 }
3417
3418 pub const fn as_variadic(self) -> Option<&'a Keyword> {
3419 match self {
3420 ArgOrKeyword::Keyword(keyword) if keyword.arg.is_none() => Some(keyword),
3421 _ => None,
3422 }
3423 }
3424}
3425
3426impl<'a> From<&'a Expr> for ArgOrKeyword<'a> {
3427 fn from(arg: &'a Expr) -> Self {
3428 Self::Arg(arg)
3429 }
3430}
3431
3432impl<'a> From<&'a Keyword> for ArgOrKeyword<'a> {
3433 fn from(keyword: &'a Keyword) -> Self {
3434 Self::Keyword(keyword)
3435 }
3436}
3437
3438impl Ranged for ArgOrKeyword<'_> {
3439 fn range(&self) -> TextRange {
3440 match self {
3441 Self::Arg(arg) => arg.range(),
3442 Self::Keyword(keyword) => keyword.range(),
3443 }
3444 }
3445}
3446
3447impl Arguments {
3448 pub fn len(&self) -> usize {
3450 self.args.len() + self.keywords.len()
3451 }
3452
3453 pub fn is_empty(&self) -> bool {
3455 self.len() == 0
3456 }
3457
3458 pub fn find_keyword(&self, keyword_name: &str) -> Option<&Keyword> {
3460 self.keywords.iter().find(|keyword| {
3461 let Keyword { arg, .. } = keyword;
3462 arg.as_ref().is_some_and(|arg| arg == keyword_name)
3463 })
3464 }
3465
3466 pub fn find_positional(&self, position: usize) -> Option<&Expr> {
3468 self.args
3469 .iter()
3470 .take_while(|expr| !expr.is_starred_expr())
3471 .nth(position)
3472 }
3473
3474 pub fn find_argument_value(&self, name: &str, position: usize) -> Option<&Expr> {
3478 self.find_argument(name, position).map(ArgOrKeyword::value)
3479 }
3480
3481 pub fn find_argument(&self, name: &str, position: usize) -> Option<ArgOrKeyword<'_>> {
3485 self.find_keyword(name)
3486 .map(ArgOrKeyword::from)
3487 .or_else(|| self.find_positional(position).map(ArgOrKeyword::from))
3488 }
3489
3490 pub fn arguments_source_order(&self) -> ArgumentsSourceOrder<'_> {
3525 ArgumentsSourceOrder {
3526 args: &self.args,
3527 keywords: &self.keywords,
3528 next_arg: 0,
3529 next_keyword: 0,
3530 }
3531 }
3532
3533 pub fn inner_range(&self) -> TextRange {
3534 TextRange::new(self.l_paren_range().end(), self.r_paren_range().start())
3535 }
3536
3537 pub fn l_paren_range(&self) -> TextRange {
3538 TextRange::at(self.start(), '('.text_len())
3539 }
3540
3541 pub fn r_paren_range(&self) -> TextRange {
3542 TextRange::new(self.end() - ')'.text_len(), self.end())
3543 }
3544}
3545
3546#[derive(Clone)]
3548pub struct ArgumentsSourceOrder<'a> {
3549 args: &'a [Expr],
3550 keywords: &'a [Keyword],
3551 next_arg: usize,
3552 next_keyword: usize,
3553}
3554
3555impl<'a> Iterator for ArgumentsSourceOrder<'a> {
3556 type Item = ArgOrKeyword<'a>;
3557
3558 fn next(&mut self) -> Option<Self::Item> {
3559 let arg = self.args.get(self.next_arg);
3560 let keyword = self.keywords.get(self.next_keyword);
3561
3562 if let Some(arg) = arg
3563 && keyword.is_none_or(|keyword| arg.start() <= keyword.start())
3564 {
3565 self.next_arg += 1;
3566 Some(ArgOrKeyword::Arg(arg))
3567 } else if let Some(keyword) = keyword {
3568 self.next_keyword += 1;
3569 Some(ArgOrKeyword::Keyword(keyword))
3570 } else {
3571 None
3572 }
3573 }
3574}
3575
3576impl FusedIterator for ArgumentsSourceOrder<'_> {}
3577
3578#[derive(Clone, Debug, PartialEq)]
3588#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3589pub struct TypeParams {
3590 pub range: TextRange,
3591 pub node_index: AtomicNodeIndex,
3592 pub type_params: Vec<TypeParam>,
3593}
3594
3595impl Deref for TypeParams {
3596 type Target = [TypeParam];
3597
3598 fn deref(&self) -> &Self::Target {
3599 &self.type_params
3600 }
3601}
3602
3603impl<'a> IntoIterator for &'a TypeParams {
3604 type Item = &'a TypeParam;
3605 type IntoIter = std::slice::Iter<'a, TypeParam>;
3606
3607 fn into_iter(self) -> Self::IntoIter {
3608 self.type_params.iter()
3609 }
3610}
3611
3612pub type Suite = Vec<Stmt>;
3616
3617#[derive(PartialEq, Eq, Debug, Clone, Hash, Copy)]
3621#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3622pub enum IpyEscapeKind {
3623 Shell,
3625 ShCap,
3627 Help,
3629 Help2,
3631 Magic,
3633 Magic2,
3635 Quote,
3638 Quote2,
3640 Paren,
3642}
3643
3644impl TryFrom<char> for IpyEscapeKind {
3645 type Error = String;
3646
3647 fn try_from(ch: char) -> Result<Self, Self::Error> {
3648 match ch {
3649 '!' => Ok(IpyEscapeKind::Shell),
3650 '?' => Ok(IpyEscapeKind::Help),
3651 '%' => Ok(IpyEscapeKind::Magic),
3652 ',' => Ok(IpyEscapeKind::Quote),
3653 ';' => Ok(IpyEscapeKind::Quote2),
3654 '/' => Ok(IpyEscapeKind::Paren),
3655 _ => Err(format!("Unexpected magic escape: {ch}")),
3656 }
3657 }
3658}
3659
3660impl TryFrom<[char; 2]> for IpyEscapeKind {
3661 type Error = String;
3662
3663 fn try_from(ch: [char; 2]) -> Result<Self, Self::Error> {
3664 match ch {
3665 ['!', '!'] => Ok(IpyEscapeKind::ShCap),
3666 ['?', '?'] => Ok(IpyEscapeKind::Help2),
3667 ['%', '%'] => Ok(IpyEscapeKind::Magic2),
3668 [c1, c2] => Err(format!("Unexpected magic escape: {c1}{c2}")),
3669 }
3670 }
3671}
3672
3673impl fmt::Display for IpyEscapeKind {
3674 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3675 f.write_str(self.as_str())
3676 }
3677}
3678
3679impl IpyEscapeKind {
3680 pub const fn is_help(self) -> bool {
3682 matches!(self, IpyEscapeKind::Help | IpyEscapeKind::Help2)
3683 }
3684
3685 pub const fn is_magic(self) -> bool {
3687 matches!(self, IpyEscapeKind::Magic | IpyEscapeKind::Magic2)
3688 }
3689
3690 pub fn as_str(self) -> &'static str {
3691 match self {
3692 IpyEscapeKind::Shell => "!",
3693 IpyEscapeKind::ShCap => "!!",
3694 IpyEscapeKind::Help => "?",
3695 IpyEscapeKind::Help2 => "??",
3696 IpyEscapeKind::Magic => "%",
3697 IpyEscapeKind::Magic2 => "%%",
3698 IpyEscapeKind::Quote => ",",
3699 IpyEscapeKind::Quote2 => ";",
3700 IpyEscapeKind::Paren => "/",
3701 }
3702 }
3703}
3704
3705#[derive(Clone, Debug, PartialEq, Eq, Hash)]
3713#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3714pub struct Identifier {
3715 pub id: Name,
3716 pub range: TextRange,
3717 pub node_index: AtomicNodeIndex,
3718}
3719
3720impl Identifier {
3721 #[inline]
3722 pub fn new(id: impl Into<Name>, range: TextRange) -> Self {
3723 Self {
3724 id: id.into(),
3725 node_index: AtomicNodeIndex::NONE,
3726 range,
3727 }
3728 }
3729
3730 pub fn id(&self) -> &Name {
3731 &self.id
3732 }
3733
3734 pub fn is_valid(&self) -> bool {
3735 !self.id.is_empty()
3736 }
3737}
3738
3739impl Identifier {
3740 #[inline]
3741 pub fn as_str(&self) -> &str {
3742 self.id.as_str()
3743 }
3744}
3745
3746impl PartialEq<str> for Identifier {
3747 #[inline]
3748 fn eq(&self, other: &str) -> bool {
3749 self.id == other
3750 }
3751}
3752
3753impl PartialEq<String> for Identifier {
3754 #[inline]
3755 fn eq(&self, other: &String) -> bool {
3756 self.id == other
3757 }
3758}
3759
3760impl std::ops::Deref for Identifier {
3761 type Target = str;
3762 #[inline]
3763 fn deref(&self) -> &Self::Target {
3764 self.id.as_str()
3765 }
3766}
3767
3768impl AsRef<str> for Identifier {
3769 #[inline]
3770 fn as_ref(&self) -> &str {
3771 self.id.as_str()
3772 }
3773}
3774
3775impl std::fmt::Display for Identifier {
3776 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3777 std::fmt::Display::fmt(&self.id, f)
3778 }
3779}
3780
3781impl From<Identifier> for Name {
3782 #[inline]
3783 fn from(identifier: Identifier) -> Name {
3784 identifier.id
3785 }
3786}
3787
3788#[derive(Clone, Copy, Debug, Hash, PartialEq)]
3789#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
3790pub enum Singleton {
3791 None,
3792 True,
3793 False,
3794}
3795
3796impl From<bool> for Singleton {
3797 fn from(value: bool) -> Self {
3798 if value {
3799 Singleton::True
3800 } else {
3801 Singleton::False
3802 }
3803 }
3804}
3805
3806#[cfg(test)]
3807mod tests {
3808 use crate::Mod;
3809 use crate::generated::*;
3810
3811 #[test]
3812 #[cfg(target_pointer_width = "64")]
3813 fn size() {
3814 assert_eq!(std::mem::size_of::<Stmt>(), 128);
3815 assert_eq!(std::mem::size_of::<StmtFunctionDef>(), 128);
3816 assert_eq!(std::mem::size_of::<StmtClassDef>(), 120);
3817 assert_eq!(std::mem::size_of::<StmtTry>(), 112);
3818 assert_eq!(std::mem::size_of::<Mod>(), 40);
3819 assert_eq!(std::mem::size_of::<Pattern>(), 104);
3820 assert_eq!(std::mem::size_of::<Expr>(), 80);
3821 assert_eq!(std::mem::size_of::<ExprAttribute>(), 64);
3822 assert_eq!(std::mem::size_of::<ExprAwait>(), 24);
3823 assert_eq!(std::mem::size_of::<ExprBinOp>(), 32);
3824 assert_eq!(std::mem::size_of::<ExprBoolOp>(), 40);
3825 assert_eq!(std::mem::size_of::<ExprBooleanLiteral>(), 16);
3826 assert_eq!(std::mem::size_of::<ExprBytesLiteral>(), 48);
3827 assert_eq!(std::mem::size_of::<ExprCall>(), 72);
3828 assert_eq!(std::mem::size_of::<ExprCompare>(), 56);
3829 assert_eq!(std::mem::size_of::<ExprDict>(), 40);
3830 assert_eq!(std::mem::size_of::<ExprDictComp>(), 56);
3831 assert_eq!(std::mem::size_of::<ExprEllipsisLiteral>(), 12);
3832 assert_eq!(std::mem::size_of::<ExprFString>(), 56);
3833 assert_eq!(std::mem::size_of::<ExprGenerator>(), 48);
3834 assert_eq!(std::mem::size_of::<ExprIf>(), 40);
3835 assert_eq!(std::mem::size_of::<ExprIpyEscapeCommand>(), 32);
3836 assert_eq!(std::mem::size_of::<ExprLambda>(), 32);
3837 assert_eq!(std::mem::size_of::<ExprList>(), 40);
3838 assert_eq!(std::mem::size_of::<ExprListComp>(), 48);
3839 assert_eq!(std::mem::size_of::<ExprName>(), 40);
3840 assert_eq!(std::mem::size_of::<ExprNamed>(), 32);
3841 assert_eq!(std::mem::size_of::<ExprNoneLiteral>(), 12);
3842 assert_eq!(std::mem::size_of::<ExprNumberLiteral>(), 40);
3843 assert_eq!(std::mem::size_of::<ExprSet>(), 40);
3844 assert_eq!(std::mem::size_of::<ExprSetComp>(), 48);
3845 assert_eq!(std::mem::size_of::<ExprSlice>(), 40);
3846 assert_eq!(std::mem::size_of::<ExprStarred>(), 24);
3847 assert_eq!(std::mem::size_of::<ExprStringLiteral>(), 64);
3848 assert_eq!(std::mem::size_of::<ExprSubscript>(), 32);
3849 assert_eq!(std::mem::size_of::<ExprTuple>(), 40);
3850 assert_eq!(std::mem::size_of::<ExprUnaryOp>(), 24);
3851 assert_eq!(std::mem::size_of::<ExprYield>(), 24);
3852 assert_eq!(std::mem::size_of::<ExprYieldFrom>(), 24);
3853 }
3854}