use ruff_python_ast::{self as ast, Arguments, ConversionFlag, Expr};
use ruff_text_size::TextRange;
fn to_interpolated_string_interpolation_element(inner: &Expr) -> ast::InterpolatedStringElement {
ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement {
expression: Box::new(inner.clone()),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
range: TextRange::default(),
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
})
}
pub(super) fn to_interpolated_string_literal_element(s: &str) -> ast::InterpolatedStringElement {
ast::InterpolatedStringElement::Literal(ast::InterpolatedStringLiteralElement {
value: Box::from(s),
range: TextRange::default(),
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
})
}
fn is_simple_call(expr: &Expr) -> bool {
match expr {
Expr::Call(ast::ExprCall {
func,
arguments:
Arguments {
args,
keywords,
range: _,
node_index: _,
},
range_start: _,
node_index: _,
}) => args.is_empty() && keywords.is_empty() && is_simple_callee(func),
_ => false,
}
}
fn is_simple_callee(func: &Expr) -> bool {
match func {
Expr::Name(_) => true,
Expr::Attribute(ast::ExprAttribute { value, .. }) => is_simple_callee(value),
_ => false,
}
}
pub(super) fn to_interpolated_string_element(
expr: &Expr,
) -> Option<ast::InterpolatedStringElement> {
match expr {
Expr::StringLiteral(ast::ExprStringLiteral {
value,
range,
node_index,
}) => Some(ast::InterpolatedStringElement::Literal(
ast::InterpolatedStringLiteralElement {
value: value.to_string().into_boxed_str(),
range: *range,
node_index: node_index.clone(),
},
)),
Expr::NumberLiteral(_) | Expr::BooleanLiteral(_) | Expr::Name(_) | Expr::Attribute(_) => {
Some(to_interpolated_string_interpolation_element(expr))
}
Expr::Call(_) if is_simple_call(expr) => {
Some(to_interpolated_string_interpolation_element(expr))
}
_ => None,
}
}