Implement basic rendering of remaining AST nodes (#3233)

This commit is contained in:
Charlie Marsh 2023-02-26 00:05:56 -05:00 committed by GitHub
parent 51bca19c1d
commit 1c75071136
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 527 additions and 48 deletions

View file

@ -1,6 +1,6 @@
use crate::core::visitor;
use crate::core::visitor::Visitor;
use crate::cst::{Alias, Excepthandler, Expr, SliceIndex, Stmt};
use crate::cst::{Alias, Excepthandler, Expr, Pattern, SliceIndex, Stmt};
use crate::trivia::{decorate_trivia, TriviaIndex, TriviaToken};
struct AttachmentVisitor {
@ -47,6 +47,14 @@ impl<'a> Visitor<'a> for AttachmentVisitor {
}
visitor::walk_slice_index(self, slice_index);
}
fn visit_pattern(&mut self, pattern: &'a mut Pattern) {
let trivia = self.index.pattern.remove(&pattern.id());
if let Some(comments) = trivia {
pattern.trivia.extend(comments);
}
visitor::walk_pattern(self, pattern);
}
}
pub fn attach(python_cst: &mut [Stmt], trivia: Vec<TriviaToken>) {

View file

@ -566,6 +566,95 @@ impl From<(rustpython_parser::ast::Excepthandler, &Locator<'_>)> for Excepthandl
}
}
impl From<(rustpython_parser::ast::Pattern, &Locator<'_>)> for Pattern {
fn from((pattern, locator): (rustpython_parser::ast::Pattern, &Locator)) -> Self {
Pattern {
location: pattern.location,
end_location: pattern.end_location,
node: match pattern.node {
rustpython_parser::ast::PatternKind::MatchValue { value } => {
PatternKind::MatchValue {
value: Box::new((*value, locator).into()),
}
}
rustpython_parser::ast::PatternKind::MatchSingleton { value } => {
PatternKind::MatchSingleton { value }
}
rustpython_parser::ast::PatternKind::MatchSequence { patterns } => {
PatternKind::MatchSequence {
patterns: patterns
.into_iter()
.map(|pattern| (pattern, locator).into())
.collect(),
}
}
rustpython_parser::ast::PatternKind::MatchMapping {
keys,
patterns,
rest,
} => PatternKind::MatchMapping {
keys: keys.into_iter().map(|key| (key, locator).into()).collect(),
patterns: patterns
.into_iter()
.map(|pattern| (pattern, locator).into())
.collect(),
rest,
},
rustpython_parser::ast::PatternKind::MatchClass {
cls,
patterns,
kwd_attrs,
kwd_patterns,
} => PatternKind::MatchClass {
cls: Box::new((*cls, locator).into()),
patterns: patterns
.into_iter()
.map(|pattern| (pattern, locator).into())
.collect(),
kwd_attrs,
kwd_patterns: kwd_patterns
.into_iter()
.map(|pattern| (pattern, locator).into())
.collect(),
},
rustpython_parser::ast::PatternKind::MatchStar { name } => {
PatternKind::MatchStar { name }
}
rustpython_parser::ast::PatternKind::MatchAs { pattern, name } => {
PatternKind::MatchAs {
pattern: pattern.map(|pattern| Box::new((*pattern, locator).into())),
name,
}
}
rustpython_parser::ast::PatternKind::MatchOr { patterns } => PatternKind::MatchOr {
patterns: patterns
.into_iter()
.map(|pattern| (pattern, locator).into())
.collect(),
},
},
trivia: vec![],
parentheses: Parenthesize::Never,
}
}
}
impl From<(rustpython_parser::ast::MatchCase, &Locator<'_>)> for MatchCase {
fn from((match_case, locator): (rustpython_parser::ast::MatchCase, &Locator)) -> Self {
MatchCase {
pattern: (match_case.pattern, locator).into(),
guard: match_case
.guard
.map(|guard| Box::new((*guard, locator).into())),
body: match_case
.body
.into_iter()
.map(|node| (node, locator).into())
.collect(),
}
}
}
impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt {
fn from((stmt, locator): (rustpython_parser::ast::Stmt, &Locator)) -> Self {
match stmt.node {
@ -875,9 +964,19 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt {
trivia: vec![],
parentheses: Parenthesize::Never,
},
rustpython_parser::ast::StmtKind::Match { .. } => {
todo!("match statement");
}
rustpython_parser::ast::StmtKind::Match { subject, cases } => Stmt {
location: stmt.location,
end_location: stmt.end_location,
node: StmtKind::Match {
subject: Box::new((*subject, locator).into()),
cases: cases
.into_iter()
.map(|node| (node, locator).into())
.collect(),
},
trivia: vec![],
parentheses: Parenthesize::Never,
},
rustpython_parser::ast::StmtKind::Raise { exc, cause } => Stmt {
location: stmt.location,
end_location: stmt.end_location,

View file

@ -166,7 +166,7 @@ fn format_slice(
upper: &SliceIndex,
step: Option<&SliceIndex>,
) -> FormatResult<()> {
// // https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices
// https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices
let lower_is_simple = if let SliceIndexKind::Index { value } = &lower.node {
is_simple_slice(value)
} else {
@ -242,6 +242,22 @@ fn format_slice(
Ok(())
}
fn format_formatted_value(
f: &mut Formatter<ASTFormatContext<'_>>,
expr: &Expr,
value: &Expr,
_conversion: usize,
format_spec: Option<&Expr>,
) -> FormatResult<()> {
write!(f, [text("!")])?;
write!(f, [value.format()])?;
if let Some(format_spec) = format_spec {
write!(f, [text(":")])?;
write!(f, [format_spec.format()])?;
}
Ok(())
}
fn format_list(
f: &mut Formatter<ASTFormatContext<'_>>,
expr: &Expr,
@ -703,6 +719,22 @@ fn format_attribute(
Ok(())
}
fn format_named_expr(
f: &mut Formatter<ASTFormatContext<'_>>,
expr: &Expr,
target: &Expr,
value: &Expr,
) -> FormatResult<()> {
write!(f, [target.format()])?;
write!(f, [text(":=")])?;
write!(f, [space()])?;
write!(f, [group(&format_args![value.format()])])?;
write!(f, [end_of_line_comments(expr)])?;
Ok(())
}
fn format_bool_op(
f: &mut Formatter<ASTFormatContext<'_>>,
expr: &Expr,
@ -825,7 +857,7 @@ impl Format<ASTFormatContext<'_>> for FormatExpr<'_> {
match &self.item.node {
ExprKind::BoolOp { op, values } => format_bool_op(f, self.item, op, values),
// ExprKind::NamedExpr { .. } => {}
ExprKind::NamedExpr { target, value } => format_named_expr(f, self.item, target, value),
ExprKind::BinOp { left, op, right } => format_bin_op(f, self.item, left, op, right),
ExprKind::UnaryOp { op, operand } => format_unary_op(f, self.item, op, operand),
ExprKind::Lambda { args, body } => format_lambda(f, self.item, args, body),
@ -859,7 +891,6 @@ impl Format<ASTFormatContext<'_>> for FormatExpr<'_> {
args,
keywords,
} => format_call(f, self.item, func, args, keywords),
// ExprKind::FormattedValue { .. } => {}
ExprKind::JoinedStr { values } => format_joined_str(f, self.item, values),
ExprKind::Constant { value, kind } => {
format_constant(f, self.item, value, kind.as_deref())
@ -875,9 +906,11 @@ impl Format<ASTFormatContext<'_>> for FormatExpr<'_> {
ExprKind::Slice { lower, upper, step } => {
format_slice(f, self.item, lower, upper, step.as_ref())
}
_ => {
unimplemented!("Implement ExprKind: {:?}", self.item.node)
}
ExprKind::FormattedValue {
value,
conversion,
format_spec,
} => format_formatted_value(f, self.item, value, *conversion, format_spec.as_deref()),
}?;
// Any trailing comments come on the lines after.

View file

@ -0,0 +1,39 @@
use ruff_formatter::prelude::*;
use ruff_formatter::write;
use crate::context::ASTFormatContext;
use crate::cst::MatchCase;
use crate::format::builders::block;
use crate::shared_traits::AsFormat;
pub struct FormatMatchCase<'a> {
item: &'a MatchCase,
}
impl AsFormat<ASTFormatContext<'_>> for MatchCase {
type Format<'a> = FormatMatchCase<'a>;
fn format(&self) -> Self::Format<'_> {
FormatMatchCase { item: self }
}
}
impl Format<ASTFormatContext<'_>> for FormatMatchCase<'_> {
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
let MatchCase {
pattern,
guard,
body,
} = self.item;
write!(f, [text("case")])?;
write!(f, [space(), pattern.format()])?;
if let Some(guard) = &guard {
write!(f, [space(), text("if"), space(), guard.format()])?;
}
write!(f, [text(":")])?;
write!(f, [block_indent(&block(body))])?;
Ok(())
}
}

View file

@ -9,8 +9,10 @@ mod comprehension;
mod excepthandler;
mod expr;
mod helpers;
mod match_case;
mod numbers;
mod operator;
mod pattern;
mod stmt;
mod strings;
mod unaryop;

View file

@ -0,0 +1,158 @@
use ruff_formatter::prelude::*;
use ruff_formatter::write;
use ruff_text_size::TextSize;
use rustpython_parser::ast::Constant;
use crate::context::ASTFormatContext;
use crate::cst::{Pattern, PatternKind};
use crate::shared_traits::AsFormat;
pub struct FormatPattern<'a> {
item: &'a Pattern,
}
impl AsFormat<ASTFormatContext<'_>> for Pattern {
type Format<'a> = FormatPattern<'a>;
fn format(&self) -> Self::Format<'_> {
FormatPattern { item: self }
}
}
impl Format<ASTFormatContext<'_>> for FormatPattern<'_> {
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
let pattern = self.item;
match &pattern.node {
PatternKind::MatchValue { value } => {
write!(f, [value.format()])?;
}
PatternKind::MatchSingleton { value } => match value {
Constant::None => write!(f, [text("None")])?,
Constant::Bool(value) => {
if *value {
write!(f, [text("True")])?;
} else {
write!(f, [text("False")])?;
}
}
_ => unreachable!("singleton pattern must be None or bool"),
},
PatternKind::MatchSequence { patterns } => {
write!(f, [text("[")])?;
if let Some(pattern) = patterns.first() {
write!(f, [pattern.format()])?;
}
for pattern in patterns.iter().skip(1) {
write!(f, [text(","), space(), pattern.format()])?;
}
write!(f, [text("]")])?;
}
PatternKind::MatchMapping {
keys,
patterns,
rest,
} => {
write!(f, [text("{")])?;
if let Some(pattern) = patterns.first() {
write!(f, [keys[0].format(), text(":"), space(), pattern.format()])?;
}
for (key, pattern) in keys.iter().skip(1).zip(patterns.iter().skip(1)) {
write!(
f,
[
text(","),
space(),
key.format(),
text(":"),
space(),
pattern.format()
]
)?;
}
if let Some(rest) = &rest {
write!(
f,
[
text(","),
space(),
text("**"),
space(),
dynamic_text(rest, TextSize::default())
]
)?;
}
write!(f, [text("}")])?;
}
PatternKind::MatchClass {
cls,
patterns,
kwd_attrs,
kwd_patterns,
} => {
write!(f, [cls.format()])?;
if !patterns.is_empty() {
write!(f, [text("(")])?;
if let Some(pattern) = patterns.first() {
write!(f, [pattern.format()])?;
}
for pattern in patterns.iter().skip(1) {
write!(f, [text(","), space(), pattern.format()])?;
}
write!(f, [text(")")])?;
}
if !kwd_attrs.is_empty() {
write!(f, [text("(")])?;
if let Some(attr) = kwd_attrs.first() {
write!(f, [dynamic_text(attr, TextSize::default())])?;
}
for attr in kwd_attrs.iter().skip(1) {
write!(
f,
[text(","), space(), dynamic_text(attr, TextSize::default())]
)?;
}
write!(f, [text(")")])?;
}
if !kwd_patterns.is_empty() {
write!(f, [text("(")])?;
if let Some(pattern) = kwd_patterns.first() {
write!(f, [pattern.format()])?;
}
for pattern in kwd_patterns.iter().skip(1) {
write!(f, [text(","), space(), pattern.format()])?;
}
write!(f, [text(")")])?;
}
}
PatternKind::MatchStar { name } => {
if let Some(name) = &name {
write!(f, [text("*"), dynamic_text(name, TextSize::default())])?;
} else {
write!(f, [text("*_")])?;
}
}
PatternKind::MatchAs { pattern, name } => {
if let Some(pattern) = &pattern {
write!(f, [pattern.format()])?;
write!(f, [space()])?;
write!(f, [text("as")])?;
write!(f, [space()])?;
}
if let Some(name) = &name {
write!(f, [dynamic_text(name, TextSize::default())])?;
} else {
write!(f, [text("_")])?;
}
}
PatternKind::MatchOr { patterns } => {
write!(f, [patterns[0].format()])?;
for pattern in patterns.iter().skip(1) {
write!(f, [space(), text("|"), space(), pattern.format()])?;
}
}
}
Ok(())
}
}

View file

@ -6,52 +6,67 @@ use ruff_text_size::TextSize;
use crate::context::ASTFormatContext;
use crate::cst::{
Alias, Arguments, Excepthandler, Expr, ExprKind, Keyword, Stmt, StmtKind, Withitem,
Alias, Arguments, Excepthandler, Expr, ExprKind, Keyword, MatchCase, Operator, Stmt, StmtKind,
Withitem,
};
use crate::format::builders::{block, join_names};
use crate::format::comments::{end_of_line_comments, leading_comments, trailing_comments};
use crate::format::helpers::is_self_closing;
use crate::shared_traits::AsFormat;
fn format_break(f: &mut Formatter<ASTFormatContext<'_>>) -> FormatResult<()> {
write!(f, [text("break")])
}
fn format_pass(f: &mut Formatter<ASTFormatContext<'_>>, stmt: &Stmt) -> FormatResult<()> {
// Write the statement body.
write!(f, [text("pass")])?;
fn format_break(f: &mut Formatter<ASTFormatContext<'_>>, stmt: &Stmt) -> FormatResult<()> {
write!(f, [text("break")])?;
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_continue(f: &mut Formatter<ASTFormatContext<'_>>) -> FormatResult<()> {
write!(f, [text("continue")])
fn format_pass(f: &mut Formatter<ASTFormatContext<'_>>, stmt: &Stmt) -> FormatResult<()> {
write!(f, [text("pass")])?;
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_global(f: &mut Formatter<ASTFormatContext<'_>>, names: &[String]) -> FormatResult<()> {
fn format_continue(f: &mut Formatter<ASTFormatContext<'_>>, stmt: &Stmt) -> FormatResult<()> {
write!(f, [text("continue")])?;
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_global(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
names: &[String],
) -> FormatResult<()> {
write!(f, [text("global")])?;
if !names.is_empty() {
write!(f, [space(), join_names(names)])?;
}
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_nonlocal(f: &mut Formatter<ASTFormatContext<'_>>, names: &[String]) -> FormatResult<()> {
fn format_nonlocal(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
names: &[String],
) -> FormatResult<()> {
write!(f, [text("nonlocal")])?;
if !names.is_empty() {
write!(f, [space(), join_names(names)])?;
}
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_delete(f: &mut Formatter<ASTFormatContext<'_>>, targets: &[Expr]) -> FormatResult<()> {
fn format_delete(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
targets: &[Expr],
) -> FormatResult<()> {
write!(f, [text("del")])?;
match targets.len() {
0 => Ok(()),
1 => write!(f, [space(), targets[0].format()]),
0 => {}
1 => write!(f, [space(), targets[0].format()])?,
_ => {
write!(
f,
@ -74,9 +89,11 @@ fn format_delete(f: &mut Formatter<ASTFormatContext<'_>>, targets: &[Expr]) -> F
if_group_breaks(&text(")")),
])
]
)
)?;
}
}
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_class_def(
@ -223,6 +240,34 @@ fn format_assign(
Ok(())
}
fn format_aug_assign(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
target: &Expr,
op: &Operator,
value: &Expr,
) -> FormatResult<()> {
write!(f, [target.format()])?;
write!(f, [text(" "), op.format(), text("=")])?;
if is_self_closing(value) {
write!(f, [space(), group(&value.format())])?;
} else {
write!(
f,
[
space(),
group(&format_args![
if_group_breaks(&text("(")),
soft_block_indent(&value.format()),
if_group_breaks(&text(")")),
])
]
)?;
}
write!(f, [end_of_line_comments(stmt)])?;
Ok(())
}
fn format_ann_assign(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
@ -268,7 +313,11 @@ fn format_for(
body: &[Stmt],
orelse: &[Stmt],
_type_comment: Option<&str>,
async_: bool,
) -> FormatResult<()> {
if async_ {
write!(f, [text("async"), space()])?;
}
write!(
f,
[
@ -351,6 +400,19 @@ fn format_if(
Ok(())
}
fn format_match(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
subject: &Expr,
cases: &[MatchCase],
) -> FormatResult<()> {
write!(f, [text("match"), space(), subject.format(), text(":")])?;
for case in cases {
write!(f, [block_indent(&case.format())])?;
}
Ok(())
}
fn format_raise(
f: &mut Formatter<ASTFormatContext<'_>>,
stmt: &Stmt,
@ -585,7 +647,6 @@ fn format_with_(
if async_ {
write!(f, [text("async"), space()])?;
}
write!(
f,
[
@ -609,7 +670,8 @@ fn format_with_(
text(":"),
block_indent(&block(body))
]
)
)?;
Ok(())
}
pub struct FormatStmt<'a> {
@ -622,10 +684,10 @@ impl Format<ASTFormatContext<'_>> for FormatStmt<'_> {
match &self.item.node {
StmtKind::Pass => format_pass(f, self.item),
StmtKind::Break => format_break(f),
StmtKind::Continue => format_continue(f),
StmtKind::Global { names } => format_global(f, names),
StmtKind::Nonlocal { names } => format_nonlocal(f, names),
StmtKind::Break => format_break(f, self.item),
StmtKind::Continue => format_continue(f, self.item),
StmtKind::Global { names } => format_global(f, self.item, names),
StmtKind::Nonlocal { names } => format_nonlocal(f, self.item, names),
StmtKind::FunctionDef {
name,
args,
@ -668,9 +730,11 @@ impl Format<ASTFormatContext<'_>> for FormatStmt<'_> {
decorator_list,
} => format_class_def(f, name, bases, keywords, body, decorator_list),
StmtKind::Return { value } => format_return(f, self.item, value.as_ref()),
StmtKind::Delete { targets } => format_delete(f, targets),
StmtKind::Delete { targets } => format_delete(f, self.item, targets),
StmtKind::Assign { targets, value, .. } => format_assign(f, self.item, targets, value),
// StmtKind::AugAssign { .. } => {}
StmtKind::AugAssign { target, op, value } => {
format_aug_assign(f, self.item, target, op, value)
}
StmtKind::AnnAssign {
target,
annotation,
@ -691,8 +755,24 @@ impl Format<ASTFormatContext<'_>> for FormatStmt<'_> {
body,
orelse,
type_comment.as_deref(),
false,
),
StmtKind::AsyncFor {
target,
iter,
body,
orelse,
type_comment,
} => format_for(
f,
self.item,
target,
iter,
body,
orelse,
type_comment.as_deref(),
true,
),
// StmtKind::AsyncFor { .. } => {}
StmtKind::While { test, body, orelse } => {
format_while(f, self.item, test, body, orelse)
}
@ -721,7 +801,7 @@ impl Format<ASTFormatContext<'_>> for FormatStmt<'_> {
type_comment.as_ref().map(String::as_str),
true,
),
// StmtKind::Match { .. } => {}
StmtKind::Match { subject, cases } => format_match(f, self.item, subject, cases),
StmtKind::Raise { exc, cause } => {
format_raise(f, self.item, exc.as_deref(), cause.as_deref())
}
@ -752,11 +832,7 @@ impl Format<ASTFormatContext<'_>> for FormatStmt<'_> {
names,
level.as_ref(),
),
// StmtKind::Nonlocal { .. } => {}
StmtKind::Expr { value } => format_expr(f, self.item, value),
_ => {
unimplemented!("Implement StmtKind: {:?}", self.item.node)
}
}?;
write!(f, [hard_line_break()])?;

View file

@ -5,8 +5,8 @@ use rustpython_parser::Tok;
use crate::core::types::Range;
use crate::cst::{
Alias, Excepthandler, ExcepthandlerKind, Expr, ExprKind, SliceIndex, SliceIndexKind, Stmt,
StmtKind,
Alias, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Pattern, PatternKind, SliceIndex,
SliceIndexKind, Stmt, StmtKind,
};
#[derive(Clone, Debug)]
@ -17,6 +17,7 @@ pub enum Node<'a> {
Alias(&'a Alias),
Excepthandler(&'a Excepthandler),
SliceIndex(&'a SliceIndex),
Pattern(&'a Pattern),
}
impl Node<'_> {
@ -28,6 +29,7 @@ impl Node<'_> {
Node::Alias(node) => node.id(),
Node::Excepthandler(node) => node.id(),
Node::SliceIndex(node) => node.id(),
Node::Pattern(node) => node.id(),
}
}
}
@ -389,8 +391,17 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
result.push(Node::Stmt(stmt));
}
}
StmtKind::Match { .. } => {
todo!("Support match statements");
StmtKind::Match { subject, cases } => {
result.push(Node::Expr(subject));
for case in cases {
result.push(Node::Pattern(&case.pattern));
if let Some(expr) = &case.guard {
result.push(Node::Expr(expr));
}
for stmt in &case.body {
result.push(Node::Stmt(stmt));
}
}
}
StmtKind::Raise { exc, cause } => {
if let Some(exc) = exc {
@ -615,7 +626,6 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
},
Node::Alias(..) => {}
Node::Excepthandler(excepthandler) => {
// TODO(charlie): Ident.
let ExcepthandlerKind::ExceptHandler { type_, body, .. } = &excepthandler.node;
if let Some(type_) = type_ {
result.push(Node::Expr(type_));
@ -629,6 +639,48 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
result.push(Node::Expr(value));
}
}
Node::Pattern(pattern) => match &pattern.node {
PatternKind::MatchValue { value } => {
result.push(Node::Expr(value));
}
PatternKind::MatchSingleton { .. } => {}
PatternKind::MatchSequence { patterns } => {
for pattern in patterns {
result.push(Node::Pattern(pattern));
}
}
PatternKind::MatchMapping { keys, patterns, .. } => {
for (key, pattern) in keys.iter().zip(patterns.iter()) {
result.push(Node::Expr(key));
result.push(Node::Pattern(pattern));
}
}
PatternKind::MatchClass {
cls,
patterns,
kwd_patterns,
..
} => {
result.push(Node::Expr(cls));
for pattern in patterns {
result.push(Node::Pattern(pattern));
}
for pattern in kwd_patterns {
result.push(Node::Pattern(pattern));
}
}
PatternKind::MatchStar { .. } => {}
PatternKind::MatchAs { pattern, .. } => {
if let Some(pattern) = pattern {
result.push(Node::Pattern(pattern));
}
}
PatternKind::MatchOr { patterns } => {
for pattern in patterns {
result.push(Node::Pattern(pattern));
}
}
},
}
}
@ -670,6 +722,7 @@ pub fn decorate_token<'a>(
Node::Alias(node) => node.location,
Node::Excepthandler(node) => node.location,
Node::SliceIndex(node) => node.location,
Node::Pattern(node) => node.location,
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
};
let end = match &child {
@ -678,6 +731,7 @@ pub fn decorate_token<'a>(
Node::Alias(node) => node.end_location.unwrap(),
Node::Excepthandler(node) => node.end_location.unwrap(),
Node::SliceIndex(node) => node.end_location.unwrap(),
Node::Pattern(node) => node.end_location.unwrap(),
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
};
@ -690,6 +744,7 @@ pub fn decorate_token<'a>(
Node::Alias(node) => node.location,
Node::Excepthandler(node) => node.location,
Node::SliceIndex(node) => node.location,
Node::Pattern(node) => node.location,
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
};
let existing_end = match &existing {
@ -698,6 +753,7 @@ pub fn decorate_token<'a>(
Node::Alias(node) => node.end_location.unwrap(),
Node::Excepthandler(node) => node.end_location.unwrap(),
Node::SliceIndex(node) => node.end_location.unwrap(),
Node::Pattern(node) => node.end_location.unwrap(),
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
};
if start == existing_start && end == existing_end {
@ -758,6 +814,7 @@ pub struct TriviaIndex {
pub alias: FxHashMap<usize, Vec<Trivia>>,
pub excepthandler: FxHashMap<usize, Vec<Trivia>>,
pub slice_index: FxHashMap<usize, Vec<Trivia>>,
pub pattern: FxHashMap<usize, Vec<Trivia>>,
}
fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
@ -798,6 +855,13 @@ fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
.or_insert_with(Vec::new)
.push(comment);
}
Node::Pattern(node) => {
trivia
.pattern
.entry(node.id())
.or_insert_with(Vec::new)
.push(comment);
}
}
}