use std::mem::swap;
use crate::{
inflate_helpers::adjust_parameters_trailing_whitespace,
nodes::{
op::*,
statement::*,
traits::{Inflate, ParenthesizedDeflatedNode, ParenthesizedNode, Result, WithComma},
whitespace::ParenthesizableWhitespace,
Annotation, AssignEqual, AssignTargetExpression, BinaryOp, BooleanOp, Codegen,
CodegenState, Colon, Comma, CompOp, Dot, UnaryOp,
},
tokenizer::{
whitespace_parser::{parse_parenthesizable_whitespace, Config},
Token,
},
};
#[cfg(feature = "py")]
use libcst_derive::TryIntoPy;
use libcst_derive::{cst_node, Codegen, Inflate, ParenthesizedDeflatedNode, ParenthesizedNode};
type TokenRef<'r, 'a> = &'r Token<'a>;
#[cst_node(Default)]
pub struct Parameters<'a> {
pub params: Vec<Param<'a>>,
pub star_arg: Option<StarArg<'a>>,
pub kwonly_params: Vec<Param<'a>>,
pub star_kwarg: Option<Param<'a>>,
pub posonly_params: Vec<Param<'a>>,
pub posonly_ind: Option<ParamSlash<'a>>,
}
impl<'a> Parameters<'a> {
pub fn is_empty(&self) -> bool {
self.params.is_empty()
&& self.star_arg.is_none()
&& self.kwonly_params.is_empty()
&& self.star_kwarg.is_none()
&& self.posonly_params.is_empty()
&& self.posonly_ind.is_none()
}
}
impl<'r, 'a> DeflatedParameters<'r, 'a> {
pub fn is_empty(&self) -> bool {
self.params.is_empty()
&& self.star_arg.is_none()
&& self.kwonly_params.is_empty()
&& self.star_kwarg.is_none()
&& self.posonly_params.is_empty()
&& self.posonly_ind.is_none()
}
}
impl<'r, 'a> Inflate<'a> for DeflatedParameters<'r, 'a> {
type Inflated = Parameters<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let posonly_params = self.posonly_params.inflate(config)?;
let posonly_ind = self.posonly_ind.inflate(config)?;
let params = self.params.inflate(config)?;
let star_arg = self.star_arg.inflate(config)?;
let kwonly_params = self.kwonly_params.inflate(config)?;
let star_kwarg = self.star_kwarg.inflate(config)?;
Ok(Self::Inflated {
params,
star_arg,
kwonly_params,
star_kwarg,
posonly_params,
posonly_ind,
})
}
}
#[cst_node(Inflate)]
pub enum StarArg<'a> {
Star(Box<ParamStar<'a>>),
Param(Box<Param<'a>>),
}
impl<'a> Codegen<'a> for Parameters<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
let params_after_kwonly = self.star_kwarg.is_some();
let params_after_regular = !self.kwonly_params.is_empty() || params_after_kwonly;
let params_after_posonly = !self.params.is_empty() || params_after_regular;
let star_included = self.star_arg.is_some() || !self.kwonly_params.is_empty();
for p in &self.posonly_params {
p.codegen(state, None, true);
}
match &self.posonly_ind {
Some(ind) => ind.codegen(state, params_after_posonly),
_ => {
if !self.posonly_params.is_empty() {
if params_after_posonly {
state.add_token("/, ");
} else {
state.add_token("/");
}
}
}
}
let param_size = self.params.len();
for (i, p) in self.params.iter().enumerate() {
p.codegen(state, None, params_after_regular || i < param_size - 1);
}
let kwonly_size = self.kwonly_params.len();
match &self.star_arg {
None => {
if star_included {
state.add_token("*, ")
}
}
Some(StarArg::Param(p)) => p.codegen(
state,
Some("*"),
kwonly_size > 0 || self.star_kwarg.is_some(),
),
Some(StarArg::Star(s)) => s.codegen(state),
}
for (i, p) in self.kwonly_params.iter().enumerate() {
p.codegen(state, None, params_after_kwonly || i < kwonly_size - 1);
}
if let Some(star) = &self.star_kwarg {
star.codegen(state, Some("**"), false)
}
}
}
#[cst_node]
pub struct ParamSlash<'a> {
pub comma: Option<Comma<'a>>,
pub whitespace_after: ParenthesizableWhitespace<'a>,
pub(crate) tok: TokenRef<'a>,
}
impl<'a> ParamSlash<'a> {
fn codegen(&self, state: &mut CodegenState<'a>, default_comma: bool) {
state.add_token("/");
self.whitespace_after.codegen(state);
match (&self.comma, default_comma) {
(Some(comma), _) => comma.codegen(state),
(None, true) => state.add_token(", "),
_ => {}
}
}
}
impl<'r, 'a> Inflate<'a> for DeflatedParamSlash<'r, 'a> {
type Inflated = ParamSlash<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_after =
parse_parenthesizable_whitespace(config, &mut self.tok.whitespace_after.borrow_mut())?;
let comma = self.comma.inflate(config)?;
Ok(Self::Inflated {
comma,
whitespace_after,
})
}
}
#[cst_node]
pub struct ParamStar<'a> {
pub comma: Comma<'a>,
}
impl<'a> Codegen<'a> for ParamStar<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("*");
self.comma.codegen(state);
}
}
impl<'r, 'a> Inflate<'a> for DeflatedParamStar<'r, 'a> {
type Inflated = ParamStar<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let comma = self.comma.inflate(config)?;
Ok(Self::Inflated { comma })
}
}
#[cst_node(ParenthesizedNode, Default)]
pub struct Name<'a> {
pub value: &'a str,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedName<'r, 'a> {
type Inflated = Name<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value: self.value,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for Name<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token(self.value);
});
}
}
#[cst_node]
pub struct Param<'a> {
pub name: Name<'a>,
pub annotation: Option<Annotation<'a>>,
pub equal: Option<AssignEqual<'a>>,
pub default: Option<Expression<'a>>,
pub comma: Option<Comma<'a>>,
pub star: Option<&'a str>,
pub whitespace_after_star: ParenthesizableWhitespace<'a>,
pub whitespace_after_param: ParenthesizableWhitespace<'a>,
pub(crate) star_tok: Option<TokenRef<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedParam<'r, 'a> {
type Inflated = Param<'a>;
fn inflate(mut self, config: &Config<'a>) -> Result<Self::Inflated> {
let name = self.name.inflate(config)?;
let annotation = self.annotation.inflate(config)?;
let equal = self.equal.inflate(config)?;
let default = self.default.inflate(config)?;
let comma = self.comma.inflate(config)?;
let whitespace_after_star = if let Some(star_tok) = self.star_tok.as_mut() {
parse_parenthesizable_whitespace(config, &mut star_tok.whitespace_after.borrow_mut())?
} else {
Default::default()
};
let whitespace_after_param = Default::default(); Ok(Self::Inflated {
name,
annotation,
equal,
default,
comma,
star: self.star,
whitespace_after_star,
whitespace_after_param,
})
}
}
impl<'r, 'a> Default for DeflatedParam<'r, 'a> {
fn default() -> Self {
Self {
name: Default::default(),
annotation: None,
equal: None,
default: None,
comma: None,
star: Some(""), star_tok: None,
}
}
}
impl<'a> Param<'a> {
fn codegen(
&self,
state: &mut CodegenState<'a>,
default_star: Option<&'a str>,
default_comma: bool,
) {
match (self.star, default_star) {
(Some(star), _) => state.add_token(star),
(None, Some(star)) => state.add_token(star),
_ => {}
}
self.whitespace_after_star.codegen(state);
self.name.codegen(state);
if let Some(ann) = &self.annotation {
ann.codegen(state, ":");
}
match (&self.equal, &self.default) {
(Some(equal), Some(def)) => {
equal.codegen(state);
def.codegen(state);
}
(None, Some(def)) => {
state.add_token(" = ");
def.codegen(state);
}
_ => {}
}
match &self.comma {
Some(comma) => comma.codegen(state),
None if default_comma => state.add_token(", "),
_ => {}
}
self.whitespace_after_param.codegen(state);
}
}
#[cst_node]
pub struct Arg<'a> {
pub value: Expression<'a>,
pub keyword: Option<Name<'a>>,
pub equal: Option<AssignEqual<'a>>,
pub comma: Option<Comma<'a>>,
pub star: &'a str,
pub whitespace_after_star: ParenthesizableWhitespace<'a>,
pub whitespace_after_arg: ParenthesizableWhitespace<'a>,
pub(crate) star_tok: Option<TokenRef<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedArg<'r, 'a> {
type Inflated = Arg<'a>;
fn inflate(mut self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_after_star = if let Some(star_tok) = self.star_tok.as_mut() {
parse_parenthesizable_whitespace(config, &mut star_tok.whitespace_after.borrow_mut())?
} else {
Default::default()
};
let keyword = self.keyword.inflate(config)?;
let equal = self.equal.inflate(config)?;
let value = self.value.inflate(config)?;
let comma = self.comma.inflate(config)?;
let whitespace_after_arg = Default::default();
Ok(Self::Inflated {
value,
keyword,
equal,
comma,
star: self.star,
whitespace_after_star,
whitespace_after_arg,
})
}
}
impl<'a> Arg<'a> {
pub fn codegen(&self, state: &mut CodegenState<'a>, default_comma: bool) {
state.add_token(self.star);
self.whitespace_after_star.codegen(state);
if let Some(kw) = &self.keyword {
kw.codegen(state);
}
if let Some(eq) = &self.equal {
eq.codegen(state);
} else if self.keyword.is_some() {
state.add_token(" = ");
}
self.value.codegen(state);
if let Some(comma) = &self.comma {
comma.codegen(state);
} else if default_comma {
state.add_token(", ");
}
self.whitespace_after_arg.codegen(state);
}
}
impl<'r, 'a> WithComma<'r, 'a> for DeflatedArg<'r, 'a> {
fn with_comma(self, c: DeflatedComma<'r, 'a>) -> Self {
Self {
comma: Some(c),
..self
}
}
}
#[cst_node]
#[derive(Default)]
pub struct LeftParen<'a> {
pub whitespace_after: ParenthesizableWhitespace<'a>,
pub(crate) lpar_tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for LeftParen<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("(");
self.whitespace_after.codegen(state);
}
}
impl<'r, 'a> Inflate<'a> for DeflatedLeftParen<'r, 'a> {
type Inflated = LeftParen<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_after = parse_parenthesizable_whitespace(
config,
&mut (*self.lpar_tok).whitespace_after.borrow_mut(),
)?;
Ok(Self::Inflated { whitespace_after })
}
}
#[cst_node]
#[derive(Default)]
pub struct RightParen<'a> {
pub whitespace_before: ParenthesizableWhitespace<'a>,
pub(crate) rpar_tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for RightParen<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.whitespace_before.codegen(state);
state.add_token(")");
}
}
impl<'r, 'a> Inflate<'a> for DeflatedRightParen<'r, 'a> {
type Inflated = RightParen<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_before = parse_parenthesizable_whitespace(
config,
&mut (*self.rpar_tok).whitespace_before.borrow_mut(),
)?;
Ok(Self::Inflated { whitespace_before })
}
}
#[cst_node(ParenthesizedNode, Codegen, Inflate)]
pub enum Expression<'a> {
Name(Box<Name<'a>>),
Ellipsis(Box<Ellipsis<'a>>),
Integer(Box<Integer<'a>>),
Float(Box<Float<'a>>),
Imaginary(Box<Imaginary<'a>>),
Comparison(Box<Comparison<'a>>),
UnaryOperation(Box<UnaryOperation<'a>>),
BinaryOperation(Box<BinaryOperation<'a>>),
BooleanOperation(Box<BooleanOperation<'a>>),
Attribute(Box<Attribute<'a>>),
Tuple(Box<Tuple<'a>>),
Call(Box<Call<'a>>),
GeneratorExp(Box<GeneratorExp<'a>>),
ListComp(Box<ListComp<'a>>),
SetComp(Box<SetComp<'a>>),
DictComp(Box<DictComp<'a>>),
List(Box<List<'a>>),
Set(Box<Set<'a>>),
Dict(Box<Dict<'a>>),
Subscript(Box<Subscript<'a>>),
StarredElement(Box<StarredElement<'a>>),
IfExp(Box<IfExp<'a>>),
Lambda(Box<Lambda<'a>>),
Yield(Box<Yield<'a>>),
Await(Box<Await<'a>>),
SimpleString(Box<SimpleString<'a>>),
ConcatenatedString(Box<ConcatenatedString<'a>>),
FormattedString(Box<FormattedString<'a>>),
NamedExpr(Box<NamedExpr<'a>>),
}
#[cst_node(ParenthesizedNode)]
pub struct Ellipsis<'a> {
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for Ellipsis<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token("...");
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedEllipsis<'r, 'a> {
type Inflated = Ellipsis<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated { lpar, rpar })
}
}
#[cst_node(ParenthesizedNode)]
pub struct Integer<'a> {
pub value: &'a str,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for Integer<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token(self.value);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedInteger<'r, 'a> {
type Inflated = Integer<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value: self.value,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Float<'a> {
pub value: &'a str,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for Float<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token(self.value);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedFloat<'r, 'a> {
type Inflated = Float<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value: self.value,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Imaginary<'a> {
pub value: &'a str,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for Imaginary<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token(self.value);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedImaginary<'r, 'a> {
type Inflated = Imaginary<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value: self.value,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Comparison<'a> {
pub left: Box<Expression<'a>>,
pub comparisons: Vec<ComparisonTarget<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for Comparison<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.left.codegen(state);
for comp in &self.comparisons {
comp.codegen(state);
}
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedComparison<'r, 'a> {
type Inflated = Comparison<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let left = self.left.inflate(config)?;
let comparisons = self.comparisons.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
left,
comparisons,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct UnaryOperation<'a> {
pub operator: UnaryOp<'a>,
pub expression: Box<Expression<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for UnaryOperation<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.operator.codegen(state);
self.expression.codegen(state);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedUnaryOperation<'r, 'a> {
type Inflated = UnaryOperation<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let operator = self.operator.inflate(config)?;
let expression = self.expression.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
operator,
expression,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct BinaryOperation<'a> {
pub left: Box<Expression<'a>>,
pub operator: BinaryOp<'a>,
pub right: Box<Expression<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for BinaryOperation<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.left.codegen(state);
self.operator.codegen(state);
self.right.codegen(state);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedBinaryOperation<'r, 'a> {
type Inflated = BinaryOperation<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let left = self.left.inflate(config)?;
let operator = self.operator.inflate(config)?;
let right = self.right.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
left,
operator,
right,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct BooleanOperation<'a> {
pub left: Box<Expression<'a>>,
pub operator: BooleanOp<'a>,
pub right: Box<Expression<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for BooleanOperation<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.left.codegen(state);
self.operator.codegen(state);
self.right.codegen(state);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedBooleanOperation<'r, 'a> {
type Inflated = BooleanOperation<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let left = self.left.inflate(config)?;
let operator = self.operator.inflate(config)?;
let right = self.right.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
left,
operator,
right,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Call<'a> {
pub func: Box<Expression<'a>>,
pub args: Vec<Arg<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_after_func: ParenthesizableWhitespace<'a>,
pub whitespace_before_args: ParenthesizableWhitespace<'a>,
pub(crate) lpar_tok: TokenRef<'a>,
pub(crate) rpar_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedCall<'r, 'a> {
type Inflated = Call<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let func = self.func.inflate(config)?;
let whitespace_after_func = parse_parenthesizable_whitespace(
config,
&mut (*self.lpar_tok).whitespace_before.borrow_mut(),
)?;
let whitespace_before_args = parse_parenthesizable_whitespace(
config,
&mut (*self.lpar_tok).whitespace_after.borrow_mut(),
)?;
let mut args = self.args.inflate(config)?;
if let Some(arg) = args.last_mut() {
if arg.comma.is_none() {
arg.whitespace_after_arg = parse_parenthesizable_whitespace(
config,
&mut (*self.rpar_tok).whitespace_before.borrow_mut(),
)?;
}
}
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
func,
args,
lpar,
rpar,
whitespace_after_func,
whitespace_before_args,
})
}
}
impl<'a> Codegen<'a> for Call<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.func.codegen(state);
self.whitespace_after_func.codegen(state);
state.add_token("(");
self.whitespace_before_args.codegen(state);
let arg_len = self.args.len();
for (i, arg) in self.args.iter().enumerate() {
arg.codegen(state, i + 1 < arg_len);
}
state.add_token(")");
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Attribute<'a> {
pub value: Box<Expression<'a>>,
pub attr: Name<'a>,
pub dot: Dot<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedAttribute<'r, 'a> {
type Inflated = Attribute<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let value = self.value.inflate(config)?;
let dot = self.dot.inflate(config)?;
let attr = self.attr.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value,
attr,
dot,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for Attribute<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.value.codegen(state);
self.dot.codegen(state);
self.attr.codegen(state);
})
}
}
#[cst_node(Codegen, Inflate)]
pub enum NameOrAttribute<'a> {
N(Box<Name<'a>>),
A(Box<Attribute<'a>>),
}
impl<'r, 'a> std::convert::From<DeflatedNameOrAttribute<'r, 'a>> for DeflatedExpression<'r, 'a> {
fn from(x: DeflatedNameOrAttribute<'r, 'a>) -> Self {
match x {
DeflatedNameOrAttribute::N(n) => Self::Name(n),
DeflatedNameOrAttribute::A(a) => Self::Attribute(a),
}
}
}
#[cst_node]
pub struct ComparisonTarget<'a> {
pub operator: CompOp<'a>,
pub comparator: Expression<'a>,
}
impl<'a> Codegen<'a> for ComparisonTarget<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.operator.codegen(state);
self.comparator.codegen(state);
}
}
impl<'r, 'a> Inflate<'a> for DeflatedComparisonTarget<'r, 'a> {
type Inflated = ComparisonTarget<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let operator = self.operator.inflate(config)?;
let comparator = self.comparator.inflate(config)?;
Ok(Self::Inflated {
operator,
comparator,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct StarredElement<'a> {
pub value: Box<Expression<'a>>,
pub comma: Option<Comma<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_before_value: ParenthesizableWhitespace<'a>,
pub(crate) star_tok: TokenRef<'a>,
}
impl<'r, 'a> DeflatedStarredElement<'r, 'a> {
pub fn inflate_element(self, config: &Config<'a>, is_last: bool) -> Result<StarredElement<'a>> {
let lpar = self.lpar.inflate(config)?;
let whitespace_before_value = parse_parenthesizable_whitespace(
config,
&mut (*self.star_tok).whitespace_after.borrow_mut(),
)?;
let value = self.value.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
let comma = if is_last {
self.comma.map(|c| c.inflate_before(config)).transpose()
} else {
self.comma.inflate(config)
}?;
Ok(StarredElement {
value,
comma,
lpar,
rpar,
whitespace_before_value,
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedStarredElement<'r, 'a> {
type Inflated = StarredElement<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
self.inflate_element(config, false)
}
}
impl<'a> Codegen<'a> for StarredElement<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token("*");
self.whitespace_before_value.codegen(state);
self.value.codegen(state);
});
if let Some(comma) = &self.comma {
comma.codegen(state);
}
}
}
#[allow(clippy::large_enum_variant)]
#[cst_node(NoIntoPy)]
pub enum Element<'a> {
Simple {
value: Expression<'a>,
comma: Option<Comma<'a>>,
},
Starred(Box<StarredElement<'a>>),
}
impl<'a> Element<'a> {
pub fn codegen(
&self,
state: &mut CodegenState<'a>,
default_comma: bool,
default_comma_whitespace: bool,
) {
match self {
Self::Simple { value, comma } => {
value.codegen(state);
if let Some(comma) = comma {
comma.codegen(state)
}
}
Self::Starred(s) => s.codegen(state),
}
let maybe_comma = match self {
Self::Simple { comma, .. } => comma,
Self::Starred(s) => &s.comma,
};
if maybe_comma.is_none() && default_comma {
state.add_token(if default_comma_whitespace { ", " } else { "," });
}
}
}
impl<'r, 'a> DeflatedElement<'r, 'a> {
pub fn inflate_element(self, config: &Config<'a>, is_last: bool) -> Result<Element<'a>> {
Ok(match self {
Self::Starred(s) => Element::Starred(Box::new(s.inflate_element(config, is_last)?)),
Self::Simple { value, comma } => Element::Simple {
value: value.inflate(config)?,
comma: if is_last {
comma.map(|c| c.inflate_before(config)).transpose()?
} else {
comma.inflate(config)?
},
},
})
}
}
impl<'r, 'a> WithComma<'r, 'a> for DeflatedElement<'r, 'a> {
fn with_comma(self, comma: DeflatedComma<'r, 'a>) -> Self {
let comma = Some(comma);
match self {
Self::Simple { value, .. } => Self::Simple { comma, value },
Self::Starred(mut s) => {
s.comma = comma;
Self::Starred(s)
}
}
}
}
impl<'r, 'a> std::convert::From<DeflatedExpression<'r, 'a>> for DeflatedElement<'r, 'a> {
fn from(e: DeflatedExpression<'r, 'a>) -> Self {
match e {
DeflatedExpression::StarredElement(e) => Self::Starred(e),
value => Self::Simple { value, comma: None },
}
}
}
#[cst_node(ParenthesizedNode, Default)]
pub struct Tuple<'a> {
pub elements: Vec<Element<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedTuple<'r, 'a> {
type Inflated = Tuple<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let len = self.elements.len();
let elements = self
.elements
.into_iter()
.enumerate()
.map(|(idx, el)| el.inflate_element(config, idx + 1 == len))
.collect::<Result<Vec<_>>>()?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elements,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for Tuple<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
let len = self.elements.len();
if len == 1 {
self.elements.first().unwrap().codegen(state, true, false);
} else {
for (idx, el) in self.elements.iter().enumerate() {
el.codegen(state, idx < len - 1, true);
}
}
});
}
}
#[cst_node(ParenthesizedNode)]
pub struct GeneratorExp<'a> {
pub elt: Box<Expression<'a>>,
pub for_in: Box<CompFor<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for GeneratorExp<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.elt.codegen(state);
self.for_in.codegen(state);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedGeneratorExp<'r, 'a> {
type Inflated = GeneratorExp<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let elt = self.elt.inflate(config)?;
let for_in = self.for_in.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elt,
for_in,
lpar,
rpar,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct ListComp<'a> {
pub elt: Box<Expression<'a>>,
pub for_in: Box<CompFor<'a>>,
pub lbracket: LeftSquareBracket<'a>,
pub rbracket: RightSquareBracket<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'a> Codegen<'a> for ListComp<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.lbracket.codegen(state);
self.elt.codegen(state);
self.for_in.codegen(state);
self.rbracket.codegen(state);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedListComp<'r, 'a> {
type Inflated = ListComp<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let lbracket = self.lbracket.inflate(config)?;
let elt = self.elt.inflate(config)?;
let for_in = self.for_in.inflate(config)?;
let rbracket = self.rbracket.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elt,
for_in,
lbracket,
rbracket,
lpar,
rpar,
})
}
}
#[cst_node]
#[derive(Default)]
pub struct LeftSquareBracket<'a> {
pub whitespace_after: ParenthesizableWhitespace<'a>,
pub(crate) tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for LeftSquareBracket<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("[");
self.whitespace_after.codegen(state);
}
}
impl<'r, 'a> Inflate<'a> for DeflatedLeftSquareBracket<'r, 'a> {
type Inflated = LeftSquareBracket<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_after = parse_parenthesizable_whitespace(
config,
&mut (*self.tok).whitespace_after.borrow_mut(),
)?;
Ok(Self::Inflated { whitespace_after })
}
}
#[cst_node]
#[derive(Default)]
pub struct RightSquareBracket<'a> {
pub whitespace_before: ParenthesizableWhitespace<'a>,
pub(crate) tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for RightSquareBracket<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.whitespace_before.codegen(state);
state.add_token("]");
}
}
impl<'r, 'a> Inflate<'a> for DeflatedRightSquareBracket<'r, 'a> {
type Inflated = RightSquareBracket<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_before = parse_parenthesizable_whitespace(
config,
&mut (*self.tok).whitespace_before.borrow_mut(),
)?;
Ok(Self::Inflated { whitespace_before })
}
}
#[cst_node(ParenthesizedNode)]
pub struct SetComp<'a> {
pub elt: Box<Expression<'a>>,
pub for_in: Box<CompFor<'a>>,
pub lbrace: LeftCurlyBrace<'a>,
pub rbrace: RightCurlyBrace<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedSetComp<'r, 'a> {
type Inflated = SetComp<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let lbrace = self.lbrace.inflate(config)?;
let elt = self.elt.inflate(config)?;
let for_in = self.for_in.inflate(config)?;
let rbrace = self.rbrace.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elt,
for_in,
lbrace,
rbrace,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for SetComp<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.lbrace.codegen(state);
self.elt.codegen(state);
self.for_in.codegen(state);
self.rbrace.codegen(state);
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct DictComp<'a> {
pub key: Box<Expression<'a>>,
pub value: Box<Expression<'a>>,
pub for_in: Box<CompFor<'a>>,
pub lbrace: LeftCurlyBrace<'a>,
pub rbrace: RightCurlyBrace<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_before_colon: ParenthesizableWhitespace<'a>,
pub whitespace_after_colon: ParenthesizableWhitespace<'a>,
pub(crate) colon_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedDictComp<'r, 'a> {
type Inflated = DictComp<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let lbrace = self.lbrace.inflate(config)?;
let key = self.key.inflate(config)?;
let whitespace_before_colon = parse_parenthesizable_whitespace(
config,
&mut (*self.colon_tok).whitespace_before.borrow_mut(),
)?;
let whitespace_after_colon = parse_parenthesizable_whitespace(
config,
&mut (*self.colon_tok).whitespace_after.borrow_mut(),
)?;
let value = self.value.inflate(config)?;
let for_in = self.for_in.inflate(config)?;
let rbrace = self.rbrace.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
key,
value,
for_in,
lbrace,
rbrace,
lpar,
rpar,
whitespace_before_colon,
whitespace_after_colon,
})
}
}
impl<'a> Codegen<'a> for DictComp<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.lbrace.codegen(state);
self.key.codegen(state);
self.whitespace_before_colon.codegen(state);
state.add_token(":");
self.whitespace_after_colon.codegen(state);
self.value.codegen(state);
self.for_in.codegen(state);
self.rbrace.codegen(state);
})
}
}
#[cst_node]
pub struct LeftCurlyBrace<'a> {
pub whitespace_after: ParenthesizableWhitespace<'a>,
pub(crate) tok: TokenRef<'a>,
}
impl<'a> Default for LeftCurlyBrace<'a> {
fn default() -> Self {
Self {
whitespace_after: Default::default(),
}
}
}
impl<'r, 'a> Inflate<'a> for DeflatedLeftCurlyBrace<'r, 'a> {
type Inflated = LeftCurlyBrace<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_after = parse_parenthesizable_whitespace(
config,
&mut (*self.tok).whitespace_after.borrow_mut(),
)?;
Ok(Self::Inflated { whitespace_after })
}
}
impl<'a> Codegen<'a> for LeftCurlyBrace<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("{");
self.whitespace_after.codegen(state);
}
}
#[cst_node]
pub struct RightCurlyBrace<'a> {
pub whitespace_before: ParenthesizableWhitespace<'a>,
pub(crate) tok: TokenRef<'a>,
}
impl<'a> Default for RightCurlyBrace<'a> {
fn default() -> Self {
Self {
whitespace_before: Default::default(),
}
}
}
impl<'r, 'a> Inflate<'a> for DeflatedRightCurlyBrace<'r, 'a> {
type Inflated = RightCurlyBrace<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_before = parse_parenthesizable_whitespace(
config,
&mut (*self.tok).whitespace_before.borrow_mut(),
)?;
Ok(Self::Inflated { whitespace_before })
}
}
impl<'a> Codegen<'a> for RightCurlyBrace<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.whitespace_before.codegen(state);
state.add_token("}");
}
}
#[cst_node]
pub struct CompFor<'a> {
pub target: AssignTargetExpression<'a>,
pub iter: Expression<'a>,
pub ifs: Vec<CompIf<'a>>,
pub inner_for_in: Option<Box<CompFor<'a>>>,
pub asynchronous: Option<Asynchronous<'a>>,
pub whitespace_before: ParenthesizableWhitespace<'a>,
pub whitespace_after_for: ParenthesizableWhitespace<'a>,
pub whitespace_before_in: ParenthesizableWhitespace<'a>,
pub whitespace_after_in: ParenthesizableWhitespace<'a>,
pub(crate) async_tok: Option<TokenRef<'a>>,
pub(crate) for_tok: TokenRef<'a>,
pub(crate) in_tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for CompFor<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.whitespace_before.codegen(state);
if let Some(asynchronous) = &self.asynchronous {
asynchronous.codegen(state);
}
state.add_token("for");
self.whitespace_after_for.codegen(state);
self.target.codegen(state);
self.whitespace_before_in.codegen(state);
state.add_token("in");
self.whitespace_after_in.codegen(state);
self.iter.codegen(state);
for if_ in &self.ifs {
if_.codegen(state);
}
if let Some(inner) = &self.inner_for_in {
inner.codegen(state);
}
}
}
impl<'r, 'a> Inflate<'a> for DeflatedCompFor<'r, 'a> {
type Inflated = CompFor<'a>;
fn inflate(mut self, config: &Config<'a>) -> Result<Self::Inflated> {
let mut whitespace_before = parse_parenthesizable_whitespace(
config,
&mut (*self.for_tok).whitespace_before.borrow_mut(),
)?;
let asynchronous = if let Some(asy_tok) = self.async_tok.as_mut() {
let mut asy_whitespace_after = parse_parenthesizable_whitespace(
config,
&mut asy_tok.whitespace_before.borrow_mut(),
)?;
swap(&mut asy_whitespace_after, &mut whitespace_before);
Some(Asynchronous {
whitespace_after: asy_whitespace_after,
})
} else {
None
};
let whitespace_after_for = parse_parenthesizable_whitespace(
config,
&mut (*self.for_tok).whitespace_after.borrow_mut(),
)?;
let target = self.target.inflate(config)?;
let whitespace_before_in = parse_parenthesizable_whitespace(
config,
&mut (*self.in_tok).whitespace_before.borrow_mut(),
)?;
let whitespace_after_in = parse_parenthesizable_whitespace(
config,
&mut (*self.in_tok).whitespace_after.borrow_mut(),
)?;
let iter = self.iter.inflate(config)?;
let ifs = self.ifs.inflate(config)?;
let inner_for_in = self.inner_for_in.inflate(config)?;
Ok(Self::Inflated {
target,
iter,
ifs,
inner_for_in,
asynchronous,
whitespace_before,
whitespace_after_for,
whitespace_before_in,
whitespace_after_in,
})
}
}
#[cst_node]
pub struct Asynchronous<'a> {
pub whitespace_after: ParenthesizableWhitespace<'a>,
}
impl<'a> Codegen<'a> for Asynchronous<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("async");
self.whitespace_after.codegen(state);
}
}
pub(crate) fn make_async<'r, 'a>() -> DeflatedAsynchronous<'r, 'a> {
DeflatedAsynchronous {
_phantom: Default::default(),
}
}
#[cst_node]
pub struct CompIf<'a> {
pub test: Expression<'a>,
pub whitespace_before: ParenthesizableWhitespace<'a>,
pub whitespace_before_test: ParenthesizableWhitespace<'a>,
pub(crate) if_tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for CompIf<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.whitespace_before.codegen(state);
state.add_token("if");
self.whitespace_before_test.codegen(state);
self.test.codegen(state);
}
}
impl<'r, 'a> Inflate<'a> for DeflatedCompIf<'r, 'a> {
type Inflated = CompIf<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_before = parse_parenthesizable_whitespace(
config,
&mut (*self.if_tok).whitespace_before.borrow_mut(),
)?;
let whitespace_before_test = parse_parenthesizable_whitespace(
config,
&mut (*self.if_tok).whitespace_after.borrow_mut(),
)?;
let test = self.test.inflate(config)?;
Ok(Self::Inflated {
test,
whitespace_before,
whitespace_before_test,
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct List<'a> {
pub elements: Vec<Element<'a>>,
pub lbracket: LeftSquareBracket<'a>,
pub rbracket: RightSquareBracket<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedList<'r, 'a> {
type Inflated = List<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let lbracket = self.lbracket.inflate(config)?;
let len = self.elements.len();
let elements = self
.elements
.into_iter()
.enumerate()
.map(|(idx, el)| el.inflate_element(config, idx + 1 == len))
.collect::<Result<Vec<_>>>()?;
let rbracket = if !elements.is_empty() {
self.rbracket.inflate(config)?
} else {
Default::default()
};
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elements,
lbracket,
rbracket,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for List<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.lbracket.codegen(state);
let len = self.elements.len();
for (idx, el) in self.elements.iter().enumerate() {
el.codegen(state, idx < len - 1, true);
}
self.rbracket.codegen(state);
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Set<'a> {
pub elements: Vec<Element<'a>>,
pub lbrace: LeftCurlyBrace<'a>,
pub rbrace: RightCurlyBrace<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedSet<'r, 'a> {
type Inflated = Set<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let lbrace = self.lbrace.inflate(config)?;
let len = self.elements.len();
let elements = self
.elements
.into_iter()
.enumerate()
.map(|(idx, el)| el.inflate_element(config, idx + 1 == len))
.collect::<Result<Vec<_>>>()?;
let rbrace = if !elements.is_empty() {
self.rbrace.inflate(config)?
} else {
Default::default()
};
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elements,
lbrace,
rbrace,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for Set<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.lbrace.codegen(state);
let len = self.elements.len();
for (idx, el) in self.elements.iter().enumerate() {
el.codegen(state, idx < len - 1, true);
}
self.rbrace.codegen(state);
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Dict<'a> {
pub elements: Vec<DictElement<'a>>,
pub lbrace: LeftCurlyBrace<'a>,
pub rbrace: RightCurlyBrace<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedDict<'r, 'a> {
type Inflated = Dict<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let lbrace = self.lbrace.inflate(config)?;
let len = self.elements.len();
let elements = self
.elements
.into_iter()
.enumerate()
.map(|(idx, el)| el.inflate_element(config, idx + 1 == len))
.collect::<Result<Vec<_>>>()?;
let rbrace = if !elements.is_empty() {
self.rbrace.inflate(config)?
} else {
Default::default()
};
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
elements,
lbrace,
rbrace,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for Dict<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.lbrace.codegen(state);
let len = self.elements.len();
for (idx, el) in self.elements.iter().enumerate() {
el.codegen(state, idx < len - 1, true);
}
self.rbrace.codegen(state);
})
}
}
#[cst_node(NoIntoPy)]
pub enum DictElement<'a> {
Simple {
key: Expression<'a>,
value: Expression<'a>,
comma: Option<Comma<'a>>,
whitespace_before_colon: ParenthesizableWhitespace<'a>,
whitespace_after_colon: ParenthesizableWhitespace<'a>,
colon_tok: TokenRef<'a>,
},
Starred(StarredDictElement<'a>),
}
impl<'r, 'a> DeflatedDictElement<'r, 'a> {
pub fn inflate_element(
self,
config: &Config<'a>,
last_element: bool,
) -> Result<DictElement<'a>> {
Ok(match self {
Self::Starred(s) => DictElement::Starred(s.inflate_element(config, last_element)?),
Self::Simple {
key,
value,
comma,
colon_tok,
..
} => {
let whitespace_before_colon = parse_parenthesizable_whitespace(
config,
&mut colon_tok.whitespace_before.borrow_mut(),
)?;
let whitespace_after_colon = parse_parenthesizable_whitespace(
config,
&mut colon_tok.whitespace_after.borrow_mut(),
)?;
DictElement::Simple {
key: key.inflate(config)?,
whitespace_before_colon,
whitespace_after_colon,
value: value.inflate(config)?,
comma: if last_element {
comma.map(|c| c.inflate_before(config)).transpose()
} else {
comma.inflate(config)
}?,
}
}
})
}
}
impl<'a> DictElement<'a> {
fn codegen(
&self,
state: &mut CodegenState<'a>,
default_comma: bool,
default_comma_whitespace: bool,
) {
match self {
Self::Simple {
key,
value,
comma,
whitespace_before_colon,
whitespace_after_colon,
..
} => {
key.codegen(state);
whitespace_before_colon.codegen(state);
state.add_token(":");
whitespace_after_colon.codegen(state);
value.codegen(state);
if let Some(comma) = comma {
comma.codegen(state)
}
}
Self::Starred(s) => s.codegen(state),
}
let maybe_comma = match self {
Self::Simple { comma, .. } => comma,
Self::Starred(s) => &s.comma,
};
if maybe_comma.is_none() && default_comma {
state.add_token(if default_comma_whitespace { ", " } else { "," });
}
}
}
impl<'r, 'a> WithComma<'r, 'a> for DeflatedDictElement<'r, 'a> {
fn with_comma(self, comma: DeflatedComma<'r, 'a>) -> Self {
let comma = Some(comma);
match self {
Self::Starred(s) => Self::Starred(DeflatedStarredDictElement { comma, ..s }),
Self::Simple {
key,
value,
colon_tok,
..
} => Self::Simple {
comma,
key,
value,
colon_tok,
},
}
}
}
#[cst_node]
pub struct StarredDictElement<'a> {
pub value: Expression<'a>,
pub comma: Option<Comma<'a>>,
pub whitespace_before_value: ParenthesizableWhitespace<'a>,
pub(crate) star_tok: TokenRef<'a>,
}
impl<'r, 'a> DeflatedStarredDictElement<'r, 'a> {
fn inflate_element(
self,
config: &Config<'a>,
last_element: bool,
) -> Result<StarredDictElement<'a>> {
let whitespace_before_value = parse_parenthesizable_whitespace(
config,
&mut (*self.star_tok).whitespace_after.borrow_mut(),
)?;
let value = self.value.inflate(config)?;
let comma = if last_element {
self.comma.map(|c| c.inflate_before(config)).transpose()
} else {
self.comma.inflate(config)
}?;
Ok(StarredDictElement {
value,
comma,
whitespace_before_value,
})
}
}
impl<'a> Codegen<'a> for StarredDictElement<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("**");
self.whitespace_before_value.codegen(state);
self.value.codegen(state);
if let Some(comma) = &self.comma {
comma.codegen(state);
}
}
}
#[cst_node(Codegen, Inflate)]
pub enum BaseSlice<'a> {
Index(Box<Index<'a>>),
Slice(Box<Slice<'a>>),
}
#[cst_node]
pub struct Index<'a> {
pub value: Expression<'a>,
pub star: Option<&'a str>,
pub whitespace_after_star: Option<ParenthesizableWhitespace<'a>>,
pub(crate) star_tok: Option<TokenRef<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedIndex<'r, 'a> {
type Inflated = Index<'a>;
fn inflate(mut self, config: &Config<'a>) -> Result<Self::Inflated> {
let (star, whitespace_after_star) = if let Some(star_tok) = self.star_tok.as_mut() {
(
Some(star_tok.string),
Some(parse_parenthesizable_whitespace(
config,
&mut star_tok.whitespace_after.borrow_mut(),
)?),
)
} else {
(None, None)
};
let value = self.value.inflate(config)?;
Ok(Self::Inflated {
value,
star,
whitespace_after_star,
})
}
}
impl<'a> Codegen<'a> for Index<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
if let Some(star) = self.star {
state.add_token(star);
}
self.whitespace_after_star.codegen(state);
self.value.codegen(state);
}
}
#[cst_node]
pub struct Slice<'a> {
#[cfg_attr(feature = "py", no_py_default)]
pub lower: Option<Expression<'a>>,
#[cfg_attr(feature = "py", no_py_default)]
pub upper: Option<Expression<'a>>,
pub step: Option<Expression<'a>>,
pub first_colon: Colon<'a>,
pub second_colon: Option<Colon<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedSlice<'r, 'a> {
type Inflated = Slice<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lower = self.lower.inflate(config)?;
let first_colon = self.first_colon.inflate(config)?;
let upper = self.upper.inflate(config)?;
let second_colon = self.second_colon.inflate(config)?;
let step = self.step.inflate(config)?;
Ok(Self::Inflated {
lower,
upper,
step,
first_colon,
second_colon,
})
}
}
impl<'a> Codegen<'a> for Slice<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
if let Some(lower) = &self.lower {
lower.codegen(state);
}
self.first_colon.codegen(state);
if let Some(upper) = &self.upper {
upper.codegen(state);
}
if let Some(second_colon) = &self.second_colon {
second_colon.codegen(state);
} else if self.step.is_some() {
state.add_token(";");
}
if let Some(step) = &self.step {
step.codegen(state);
}
}
}
#[cst_node]
pub struct SubscriptElement<'a> {
pub slice: BaseSlice<'a>,
pub comma: Option<Comma<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedSubscriptElement<'r, 'a> {
type Inflated = SubscriptElement<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let slice = self.slice.inflate(config)?;
let comma = self.comma.inflate(config)?;
Ok(Self::Inflated { slice, comma })
}
}
impl<'a> Codegen<'a> for SubscriptElement<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.slice.codegen(state);
if let Some(comma) = &self.comma {
comma.codegen(state);
}
}
}
#[cst_node(ParenthesizedNode)]
pub struct Subscript<'a> {
pub value: Box<Expression<'a>>,
pub slice: Vec<SubscriptElement<'a>>,
pub lbracket: LeftSquareBracket<'a>,
pub rbracket: RightSquareBracket<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_after_value: ParenthesizableWhitespace<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedSubscript<'r, 'a> {
type Inflated = Subscript<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let value = self.value.inflate(config)?;
let whitespace_after_value = parse_parenthesizable_whitespace(
config,
&mut self.lbracket.tok.whitespace_before.borrow_mut(),
)?;
let lbracket = self.lbracket.inflate(config)?;
let slice = self.slice.inflate(config)?;
let rbracket = self.rbracket.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value,
slice,
lbracket,
rbracket,
lpar,
rpar,
whitespace_after_value,
})
}
}
impl<'a> Codegen<'a> for Subscript<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.value.codegen(state);
self.whitespace_after_value.codegen(state);
self.lbracket.codegen(state);
let len = self.slice.len();
for (i, slice) in self.slice.iter().enumerate() {
slice.codegen(state);
if slice.comma.is_none() && i + 1 < len {
state.add_token(", ")
}
}
self.rbracket.codegen(state);
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct IfExp<'a> {
pub test: Box<Expression<'a>>,
pub body: Box<Expression<'a>>,
pub orelse: Box<Expression<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_before_if: ParenthesizableWhitespace<'a>,
pub whitespace_after_if: ParenthesizableWhitespace<'a>,
pub whitespace_before_else: ParenthesizableWhitespace<'a>,
pub whitespace_after_else: ParenthesizableWhitespace<'a>,
pub(crate) if_tok: TokenRef<'a>,
pub(crate) else_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedIfExp<'r, 'a> {
type Inflated = IfExp<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let body = self.body.inflate(config)?;
let whitespace_before_if = parse_parenthesizable_whitespace(
config,
&mut (*self.if_tok).whitespace_before.borrow_mut(),
)?;
let whitespace_after_if = parse_parenthesizable_whitespace(
config,
&mut (*self.if_tok).whitespace_after.borrow_mut(),
)?;
let test = self.test.inflate(config)?;
let whitespace_before_else = parse_parenthesizable_whitespace(
config,
&mut (*self.else_tok).whitespace_before.borrow_mut(),
)?;
let whitespace_after_else = parse_parenthesizable_whitespace(
config,
&mut (*self.else_tok).whitespace_after.borrow_mut(),
)?;
let orelse = self.orelse.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
test,
body,
orelse,
lpar,
rpar,
whitespace_before_if,
whitespace_after_if,
whitespace_before_else,
whitespace_after_else,
})
}
}
impl<'a> Codegen<'a> for IfExp<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.body.codegen(state);
self.whitespace_before_if.codegen(state);
state.add_token("if");
self.whitespace_after_if.codegen(state);
self.test.codegen(state);
self.whitespace_before_else.codegen(state);
state.add_token("else");
self.whitespace_after_else.codegen(state);
self.orelse.codegen(state);
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Lambda<'a> {
pub params: Box<Parameters<'a>>,
pub body: Box<Expression<'a>>,
pub colon: Colon<'a>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_after_lambda: Option<ParenthesizableWhitespace<'a>>,
pub(crate) lambda_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedLambda<'r, 'a> {
type Inflated = Lambda<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let whitespace_after_lambda = if !self.params.is_empty() {
Some(parse_parenthesizable_whitespace(
config,
&mut (*self.lambda_tok).whitespace_after.borrow_mut(),
)?)
} else {
Default::default()
};
let mut params = self.params.inflate(config)?;
adjust_parameters_trailing_whitespace(config, &mut params, &self.colon.tok)?;
let colon = self.colon.inflate(config)?;
let body = self.body.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
params,
body,
colon,
lpar,
rpar,
whitespace_after_lambda,
})
}
}
impl<'a> Codegen<'a> for Lambda<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token("lambda");
if let Some(ws) = &self.whitespace_after_lambda {
ws.codegen(state);
} else if !self.params.is_empty() {
state.add_token(" ")
}
self.params.codegen(state);
self.colon.codegen(state);
self.body.codegen(state);
})
}
}
#[cst_node]
pub struct From<'a> {
pub item: Expression<'a>,
pub whitespace_before_from: Option<ParenthesizableWhitespace<'a>>,
pub whitespace_after_from: ParenthesizableWhitespace<'a>,
pub(crate) tok: TokenRef<'a>,
}
impl<'a> From<'a> {
pub fn codegen(&self, state: &mut CodegenState<'a>, default_space: &'a str) {
if let Some(ws) = &self.whitespace_before_from {
ws.codegen(state);
} else {
state.add_token(default_space);
}
state.add_token("from");
self.whitespace_after_from.codegen(state);
self.item.codegen(state);
}
}
impl<'r, 'a> Inflate<'a> for DeflatedFrom<'r, 'a> {
type Inflated = From<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_before_from = Some(parse_parenthesizable_whitespace(
config,
&mut (*self.tok).whitespace_before.borrow_mut(),
)?);
let whitespace_after_from = parse_parenthesizable_whitespace(
config,
&mut (*self.tok).whitespace_after.borrow_mut(),
)?;
let item = self.item.inflate(config)?;
Ok(Self::Inflated {
item,
whitespace_before_from,
whitespace_after_from,
})
}
}
#[cst_node]
pub enum YieldValue<'a> {
Expression(Box<Expression<'a>>),
From(Box<From<'a>>),
}
impl<'r, 'a> Inflate<'a> for DeflatedYieldValue<'r, 'a> {
type Inflated = YieldValue<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
Ok(match self {
Self::Expression(e) => Self::Inflated::Expression(e.inflate(config)?),
Self::From(e) => {
let mut e = e.inflate(config)?;
e.whitespace_before_from = None;
Self::Inflated::From(e)
}
})
}
}
impl<'a> YieldValue<'a> {
fn codegen(&self, state: &mut CodegenState<'a>, default_space: &'a str) {
match self {
Self::Expression(e) => e.codegen(state),
Self::From(f) => f.codegen(state, default_space),
}
}
}
#[cst_node(ParenthesizedNode)]
pub struct Yield<'a> {
pub value: Option<Box<YieldValue<'a>>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_after_yield: Option<ParenthesizableWhitespace<'a>>,
pub(crate) yield_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedYield<'r, 'a> {
type Inflated = Yield<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let whitespace_after_yield = if self.value.is_some() {
Some(parse_parenthesizable_whitespace(
config,
&mut (*self.yield_tok).whitespace_after.borrow_mut(),
)?)
} else {
Default::default()
};
let value = self.value.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value,
lpar,
rpar,
whitespace_after_yield,
})
}
}
impl<'a> Codegen<'a> for Yield<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token("yield");
if let Some(ws) = &self.whitespace_after_yield {
ws.codegen(state);
} else if self.value.is_some() {
state.add_token(" ");
}
if let Some(val) = &self.value {
val.codegen(state, "")
}
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct Await<'a> {
pub expression: Box<Expression<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_after_await: ParenthesizableWhitespace<'a>,
pub(crate) await_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedAwait<'r, 'a> {
type Inflated = Await<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let whitespace_after_await = parse_parenthesizable_whitespace(
config,
&mut (*self.await_tok).whitespace_after.borrow_mut(),
)?;
let expression = self.expression.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
expression,
lpar,
rpar,
whitespace_after_await,
})
}
}
impl<'a> Codegen<'a> for Await<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token("await");
self.whitespace_after_await.codegen(state);
self.expression.codegen(state);
})
}
}
#[cst_node(Codegen, Inflate)]
pub enum String<'a> {
Simple(SimpleString<'a>),
Concatenated(ConcatenatedString<'a>),
Formatted(FormattedString<'a>),
}
impl<'r, 'a> std::convert::From<DeflatedString<'r, 'a>> for DeflatedExpression<'r, 'a> {
fn from(s: DeflatedString<'r, 'a>) -> Self {
match s {
DeflatedString::Simple(s) => Self::SimpleString(Box::new(s)),
DeflatedString::Concatenated(s) => Self::ConcatenatedString(Box::new(s)),
DeflatedString::Formatted(s) => Self::FormattedString(Box::new(s)),
}
}
}
#[cst_node(ParenthesizedNode)]
pub struct ConcatenatedString<'a> {
pub left: Box<String<'a>>,
pub right: Box<String<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_between: ParenthesizableWhitespace<'a>,
pub(crate) right_tok: TokenRef<'a>,
}
impl<'r, 'a> Inflate<'a> for DeflatedConcatenatedString<'r, 'a> {
type Inflated = ConcatenatedString<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let left = self.left.inflate(config)?;
let whitespace_between = parse_parenthesizable_whitespace(
config,
&mut (*self.right_tok).whitespace_before.borrow_mut(),
)?;
let right = self.right.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
left,
right,
lpar,
rpar,
whitespace_between,
})
}
}
impl<'a> Codegen<'a> for ConcatenatedString<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.left.codegen(state);
self.whitespace_between.codegen(state);
self.right.codegen(state);
})
}
}
#[cst_node(ParenthesizedNode, Default)]
pub struct SimpleString<'a> {
pub value: &'a str,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedSimpleString<'r, 'a> {
type Inflated = SimpleString<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
value: self.value,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for SimpleString<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| state.add_token(self.value))
}
}
#[cst_node]
pub struct FormattedStringText<'a> {
pub value: &'a str,
}
impl<'r, 'a> Inflate<'a> for DeflatedFormattedStringText<'r, 'a> {
type Inflated = FormattedStringText<'a>;
fn inflate(self, _config: &Config<'a>) -> Result<Self::Inflated> {
Ok(Self::Inflated { value: self.value })
}
}
impl<'a> Codegen<'a> for FormattedStringText<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token(self.value);
}
}
pub(crate) fn make_fstringtext<'r, 'a>(value: &'a str) -> DeflatedFormattedStringText<'r, 'a> {
DeflatedFormattedStringText {
value,
_phantom: Default::default(),
}
}
#[cst_node]
pub struct FormattedStringExpression<'a> {
pub expression: Expression<'a>,
pub conversion: Option<&'a str>,
pub format_spec: Option<Vec<FormattedStringContent<'a>>>,
pub whitespace_before_expression: ParenthesizableWhitespace<'a>,
pub whitespace_after_expression: ParenthesizableWhitespace<'a>,
pub equal: Option<AssignEqual<'a>>,
pub(crate) lbrace_tok: TokenRef<'a>,
pub(crate) after_expr_tok: Option<TokenRef<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedFormattedStringExpression<'r, 'a> {
type Inflated = FormattedStringExpression<'a>;
fn inflate(mut self, config: &Config<'a>) -> Result<Self::Inflated> {
let whitespace_before_expression = parse_parenthesizable_whitespace(
config,
&mut (*self.lbrace_tok).whitespace_after.borrow_mut(),
)?;
let expression = self.expression.inflate(config)?;
let equal = self.equal.inflate(config)?;
let whitespace_after_expression = if let Some(after_expr_tok) = self.after_expr_tok.as_mut()
{
parse_parenthesizable_whitespace(
config,
&mut after_expr_tok.whitespace_before.borrow_mut(),
)?
} else {
Default::default()
};
let format_spec = self.format_spec.inflate(config)?;
Ok(Self::Inflated {
expression,
conversion: self.conversion,
format_spec,
whitespace_before_expression,
whitespace_after_expression,
equal,
})
}
}
impl<'a> Codegen<'a> for FormattedStringExpression<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
state.add_token("{");
self.whitespace_before_expression.codegen(state);
self.expression.codegen(state);
if let Some(eq) = &self.equal {
eq.codegen(state);
}
self.whitespace_after_expression.codegen(state);
if let Some(conv) = &self.conversion {
state.add_token("!");
state.add_token(conv);
}
if let Some(specs) = &self.format_spec {
state.add_token(":");
for spec in specs {
spec.codegen(state);
}
}
state.add_token("}");
}
}
#[cst_node(Codegen, Inflate)]
pub enum FormattedStringContent<'a> {
Text(FormattedStringText<'a>),
Expression(Box<FormattedStringExpression<'a>>),
}
#[cst_node(ParenthesizedNode)]
pub struct FormattedString<'a> {
pub parts: Vec<FormattedStringContent<'a>>,
pub start: &'a str,
pub end: &'a str,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
}
impl<'r, 'a> Inflate<'a> for DeflatedFormattedString<'r, 'a> {
type Inflated = FormattedString<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let parts = self.parts.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
parts,
start: self.start,
end: self.end,
lpar,
rpar,
})
}
}
impl<'a> Codegen<'a> for FormattedString<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
state.add_token(self.start);
for part in &self.parts {
part.codegen(state);
}
state.add_token(self.end);
})
}
}
#[cst_node(ParenthesizedNode)]
pub struct NamedExpr<'a> {
pub target: Box<Expression<'a>>,
pub value: Box<Expression<'a>>,
pub lpar: Vec<LeftParen<'a>>,
pub rpar: Vec<RightParen<'a>>,
pub whitespace_before_walrus: ParenthesizableWhitespace<'a>,
pub whitespace_after_walrus: ParenthesizableWhitespace<'a>,
pub(crate) walrus_tok: TokenRef<'a>,
}
impl<'a> Codegen<'a> for NamedExpr<'a> {
fn codegen(&self, state: &mut CodegenState<'a>) {
self.parenthesize(state, |state| {
self.target.codegen(state);
self.whitespace_before_walrus.codegen(state);
state.add_token(":=");
self.whitespace_after_walrus.codegen(state);
self.value.codegen(state);
})
}
}
impl<'r, 'a> Inflate<'a> for DeflatedNamedExpr<'r, 'a> {
type Inflated = NamedExpr<'a>;
fn inflate(self, config: &Config<'a>) -> Result<Self::Inflated> {
let lpar = self.lpar.inflate(config)?;
let target = self.target.inflate(config)?;
let whitespace_before_walrus = parse_parenthesizable_whitespace(
config,
&mut self.walrus_tok.whitespace_before.borrow_mut(),
)?;
let whitespace_after_walrus = parse_parenthesizable_whitespace(
config,
&mut self.walrus_tok.whitespace_after.borrow_mut(),
)?;
let value = self.value.inflate(config)?;
let rpar = self.rpar.inflate(config)?;
Ok(Self::Inflated {
target,
value,
lpar,
rpar,
whitespace_before_walrus,
whitespace_after_walrus,
})
}
}
#[cfg(feature = "py")]
mod py {
use pyo3::types::PyModule;
use super::*;
use crate::nodes::traits::py::TryIntoPy;
impl<'a> TryIntoPy<pyo3::PyObject> for Element<'a> {
fn try_into_py(self, py: pyo3::Python) -> pyo3::PyResult<pyo3::PyObject> {
match self {
Self::Starred(s) => s.try_into_py(py),
Self::Simple { value, comma } => {
let libcst = PyModule::import(py, "libcst")?;
let kwargs = [
Some(("value", value.try_into_py(py)?)),
comma
.map(|x| x.try_into_py(py))
.transpose()?
.map(|x| ("comma", x)),
]
.iter()
.filter(|x| x.is_some())
.map(|x| x.as_ref().unwrap())
.collect::<Vec<_>>()
.into_py_dict(py);
Ok(libcst
.getattr("Element")
.expect("no Element found in libcst")
.call((), Some(kwargs))?
.into())
}
}
}
}
impl<'a> TryIntoPy<pyo3::PyObject> for DictElement<'a> {
fn try_into_py(self, py: pyo3::Python) -> pyo3::PyResult<pyo3::PyObject> {
match self {
Self::Starred(s) => s.try_into_py(py),
Self::Simple {
key,
value,
comma,
whitespace_after_colon,
whitespace_before_colon,
..
} => {
let libcst = PyModule::import(py, "libcst")?;
let kwargs = [
Some(("key", key.try_into_py(py)?)),
Some(("value", value.try_into_py(py)?)),
Some((
"whitespace_before_colon",
whitespace_before_colon.try_into_py(py)?,
)),
Some((
"whitespace_after_colon",
whitespace_after_colon.try_into_py(py)?,
)),
comma
.map(|x| x.try_into_py(py))
.transpose()?
.map(|x| ("comma", x)),
]
.iter()
.filter(|x| x.is_some())
.map(|x| x.as_ref().unwrap())
.collect::<Vec<_>>()
.into_py_dict(py);
Ok(libcst
.getattr("DictElement")
.expect("no Element found in libcst")
.call((), Some(kwargs))?
.into())
}
}
}
}
}