libcst_native/nodes/
traits.rs1use crate::{
7 nodes::expression::{DeflatedLeftParen, DeflatedRightParen},
8 nodes::op::DeflatedComma,
9 tokenizer::whitespace_parser::{Config, WhitespaceError},
10 Codegen, CodegenState, EmptyLine, LeftParen, RightParen,
11};
12use std::ops::Deref;
13
14pub trait WithComma<'r, 'a> {
15 fn with_comma(self, comma: DeflatedComma<'r, 'a>) -> Self;
16}
17
18pub trait ParenthesizedNode<'a> {
19 fn lpar(&self) -> &Vec<LeftParen<'a>>;
20 fn rpar(&self) -> &Vec<RightParen<'a>>;
21
22 fn parenthesize<F>(&self, state: &mut CodegenState<'a>, f: F)
23 where
24 F: FnOnce(&mut CodegenState<'a>),
25 {
26 for lpar in self.lpar() {
27 lpar.codegen(state);
28 }
29 f(state);
30 for rpar in self.rpar() {
31 rpar.codegen(state);
32 }
33 }
34
35 fn with_parens(self, left: LeftParen<'a>, right: RightParen<'a>) -> Self;
36}
37
38impl<'a, T: ParenthesizedNode<'a>> ParenthesizedNode<'a> for Box<T> {
39 fn lpar(&self) -> &Vec<LeftParen<'a>> {
40 self.deref().lpar()
41 }
42 fn rpar(&self) -> &Vec<RightParen<'a>> {
43 self.deref().rpar()
44 }
45 fn parenthesize<F>(&self, state: &mut CodegenState<'a>, f: F)
46 where
47 F: FnOnce(&mut CodegenState<'a>),
48 {
49 self.deref().parenthesize(state, f)
50 }
51 fn with_parens(self, left: LeftParen<'a>, right: RightParen<'a>) -> Self {
52 Self::new((*self).with_parens(left, right))
53 }
54}
55
56pub trait ParenthesizedDeflatedNode<'r, 'a> {
57 fn lpar(&self) -> &Vec<DeflatedLeftParen<'r, 'a>>;
58 fn rpar(&self) -> &Vec<DeflatedRightParen<'r, 'a>>;
59
60 fn with_parens(
61 self,
62 left: DeflatedLeftParen<'r, 'a>,
63 right: DeflatedRightParen<'r, 'a>,
64 ) -> Self;
65}
66impl<'r, 'a, T: ParenthesizedDeflatedNode<'r, 'a>> ParenthesizedDeflatedNode<'r, 'a> for Box<T> {
67 fn lpar(&self) -> &Vec<DeflatedLeftParen<'r, 'a>> {
68 self.deref().lpar()
69 }
70 fn rpar(&self) -> &Vec<DeflatedRightParen<'r, 'a>> {
71 self.deref().rpar()
72 }
73 fn with_parens(
74 self,
75 left: DeflatedLeftParen<'r, 'a>,
76 right: DeflatedRightParen<'r, 'a>,
77 ) -> Self {
78 Self::new((*self).with_parens(left, right))
79 }
80}
81
82pub trait WithLeadingLines<'a> {
83 fn leading_lines(&mut self) -> &mut Vec<EmptyLine<'a>>;
84}
85
86pub type Result<T> = std::result::Result<T, WhitespaceError>;
87
88pub trait Inflate<'a>
89where
90 Self: Sized,
91{
92 type Inflated;
93 fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated>;
94}
95
96impl<'a, T: Inflate<'a>> Inflate<'a> for Option<T> {
97 type Inflated = Option<T::Inflated>;
98 fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
99 self.map(|x| x.inflate(config)).transpose()
100 }
101}
102
103impl<'a, T: Inflate<'a> + ?Sized> Inflate<'a> for Box<T> {
104 type Inflated = Box<T::Inflated>;
105 fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
106 match (*self).inflate(config) {
107 Ok(a) => Ok(Box::new(a)),
108 Err(e) => Err(e),
109 }
110 }
111}
112
113impl<'a, T: Inflate<'a>> Inflate<'a> for Vec<T> {
114 type Inflated = Vec<T::Inflated>;
115 fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
116 self.into_iter().map(|item| item.inflate(config)).collect()
117 }
118}
119#[cfg(feature = "py")]
120pub mod py {
121 use pyo3::{types::PyTuple, IntoPyObjectExt, Py, PyAny, PyResult, Python};
122
123 pub trait TryIntoPy<T>: Sized {
126 fn try_into_py(self, py: Python) -> PyResult<T>;
127 }
128
129 impl TryIntoPy<Py<PyAny>> for bool {
137 fn try_into_py(self, py: Python) -> PyResult<Py<PyAny>> {
138 self.into_py_any(py)
139 }
140 }
141
142 impl<T: TryIntoPy<Py<PyAny>>> TryIntoPy<Py<PyAny>> for Box<T>
143 where
144 T: TryIntoPy<Py<PyAny>>,
145 {
146 fn try_into_py(self, py: Python) -> PyResult<Py<PyAny>> {
147 (*self).try_into_py(py)
148 }
149 }
150
151 impl<T> TryIntoPy<Py<PyAny>> for Option<T>
152 where
153 T: TryIntoPy<Py<PyAny>>,
154 {
155 fn try_into_py(self, py: Python) -> PyResult<Py<PyAny>> {
156 Ok(match self {
157 None => py.None(),
158 Some(x) => x.try_into_py(py)?,
159 })
160 }
161 }
162
163 impl<T> TryIntoPy<Py<PyAny>> for Vec<T>
164 where
165 T: TryIntoPy<Py<PyAny>>,
166 {
167 fn try_into_py(self, py: Python) -> PyResult<Py<PyAny>> {
168 let converted = self
169 .into_iter()
170 .map(|x| x.try_into_py(py))
171 .collect::<PyResult<Vec<_>>>()?
172 .into_iter();
173 PyTuple::new(py, converted)?.into_py_any(py)
174 }
175 }
176
177 impl<'a> TryIntoPy<Py<PyAny>> for &'a str {
178 fn try_into_py(self, py: Python) -> PyResult<Py<PyAny>> {
179 self.into_py_any(py)
180 }
181 }
182}