Refactor: introduce NodeInfo and needs_indent

This commit is contained in:
Joshua Warner 2024-12-20 09:54:04 -05:00
parent 13ec99c16b
commit d2e1c12b96
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
4 changed files with 55 additions and 33 deletions

View file

@ -1,7 +1,7 @@
use crate::{
collection::{fmt_collection, Braces},
expr::merge_spaces_conservative,
node::{parens_around_node, Item, Node, NodeSequenceBuilder, Nodify, Sp},
node::{parens_around_node, Item, Node, NodeInfo, NodeSequenceBuilder, Nodify, Sp},
pattern::pattern_lift_spaces_after,
pattern::snakify_camel_ident,
spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT},
@ -416,18 +416,14 @@ fn fmt_tag_collection<'a>(
}
impl<'a> Nodify<'a> for Tag<'a> {
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> Spaces<'b, Node<'b>>
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> NodeInfo<'b>
where
'a: 'b,
{
match self {
Tag::Apply { name, args } => {
if args.is_empty() {
Spaces {
before: &[],
item: Node::Literal(name.value),
after: &[],
}
NodeInfo::item(Node::Literal(name.value))
} else {
let first = Node::Literal(name.value);
let mut new_args: Vec<'b, (Sp<'b>, Node<'b>)> =
@ -441,7 +437,7 @@ impl<'a> Nodify<'a> for Tag<'a> {
new_args.push((Sp::with_space(before), lifted.item));
}
Spaces {
NodeInfo {
before: &[],
item: Node::Sequence {
first: arena.alloc(first),
@ -449,6 +445,7 @@ impl<'a> Nodify<'a> for Tag<'a> {
rest: new_args.into_bump_slice(),
},
after: last_after,
needs_indent: true,
}
}
}
@ -611,7 +608,7 @@ impl<'a> Formattable for AssignedField<'a, Expr<'a>> {
}
impl<'a> Nodify<'a> for AssignedField<'a, TypeAnnotation<'a>> {
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> Spaces<'b, Node<'b>>
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> NodeInfo<'b>
where
'a: 'b,
{
@ -628,10 +625,11 @@ impl<'a> Nodify<'a> for AssignedField<'a, TypeAnnotation<'a>> {
AssignedField::OptionalValue(name, sp, value) => {
assigned_field_value_to_node(name.value, arena, sp, &value.value, "?")
}
AssignedField::LabelOnly(name) => Spaces {
AssignedField::LabelOnly(name) => NodeInfo {
before: &[],
item: Node::Literal(name.value),
after: &[],
needs_indent: true,
},
AssignedField::SpaceBefore(inner, sp) => {
let mut inner = inner.to_node(arena, parens);
@ -653,7 +651,7 @@ fn assigned_field_value_to_node<'a, 'b>(
sp: &'a [CommentOrNewline<'a>],
value: &'a TypeAnnotation<'a>,
sep: &'static str,
) -> Spaces<'b, Node<'b>>
) -> NodeInfo<'b>
where
'a: 'b,
{
@ -667,10 +665,11 @@ where
b.push(Sp::with_space(value_lifted.before), value_lifted.item);
Spaces {
NodeInfo {
before: &[],
item: b.build(),
after: value_lifted.after,
needs_indent: true,
}
}
@ -1206,7 +1205,7 @@ pub fn type_head_lift_spaces_after<'a, 'b: 'a>(
}
impl<'a> Nodify<'a> for TypeAnnotation<'a> {
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> Spaces<'b, Node<'b>>
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> NodeInfo<'b>
where
'a: 'b,
{
@ -1234,7 +1233,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
});
}
let item = Spaces {
let item = NodeInfo {
before: &[],
item: Node::CommaSequence {
allow_blank_lines: false,
@ -1243,6 +1242,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
rest: rest.into_bump_slice(),
},
after: last_after,
needs_indent: true,
};
if parens == Parens::InApply && !args.is_empty() {
@ -1313,7 +1313,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
node: res_node.item,
});
let item = Spaces {
let item = NodeInfo {
before: first_node.before,
item: Node::CommaSequence {
allow_blank_lines: false,
@ -1322,6 +1322,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
rest: rest_nodes.into_bump_slice(),
},
after: res_node.after,
needs_indent: true,
};
if parens == Parens::InCollection
@ -1342,10 +1343,11 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
b.push(Sp::with_space(before_as), Node::Literal("as"));
b.push(Sp::with_space(right.before), right.item);
let item = Spaces {
let item = NodeInfo {
before: left.before,
item: b.build(),
after: right.after,
needs_indent: true,
};
if parens == Parens::InApply || parens == Parens::InAsPattern {
@ -1355,7 +1357,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
}
}
TypeAnnotation::BoundVariable(text) => {
let item = Spaces::item(Node::Literal(text));
let item = NodeInfo::item(Node::Literal(text));
if *text == "implements" {
parens_around_node(arena, item, false)
@ -1363,15 +1365,16 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
item
}
}
TypeAnnotation::Inferred => Spaces::item(Node::Literal("_")),
TypeAnnotation::Wildcard => Spaces::item(Node::Literal("*")),
TypeAnnotation::Malformed(text) => Spaces::item(Node::Literal(text)),
TypeAnnotation::Inferred => NodeInfo::item(Node::Literal("_")),
TypeAnnotation::Wildcard => NodeInfo::item(Node::Literal("*")),
TypeAnnotation::Malformed(text) => NodeInfo::item(Node::Literal(text)),
_ => {
let lifted = ann_lift_spaces(arena, self);
Spaces {
NodeInfo {
before: lifted.before,
item: Node::TypeAnnotation(lifted.item),
after: lifted.after,
needs_indent: true,
}
}
}

View file

@ -7,7 +7,7 @@ use crate::expr::{
expr_lift_and_lower, expr_lift_spaces, expr_lift_spaces_after, expr_lift_spaces_before,
fmt_str_literal, is_str_multiline, sub_expr_requests_parens,
};
use crate::node::Nodify;
use crate::node::{NodeInfo, Nodify};
use crate::pattern::pattern_lift_spaces_before;
use crate::pattern::{pattern_apply_to_node, pattern_fmt_apply};
use crate::spaces::{
@ -542,7 +542,7 @@ impl<'a> Formattable for TypeHeader<'a> {
}
impl<'a> Nodify<'a> for TypeHeader<'a> {
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> Spaces<'b, crate::node::Node<'b>>
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> NodeInfo<'b>
where
'a: 'b,
{

View file

@ -1,5 +1,5 @@
use bumpalo::{collections::Vec, Bump};
use roc_parse::ast::{CommentOrNewline, Pattern, Spaces, TypeAnnotation};
use roc_parse::ast::{CommentOrNewline, Pattern, TypeAnnotation};
use crate::{
annotation::{Formattable, Newlines, Parens},
@ -98,12 +98,12 @@ impl<'a> Node<'a> {
}
}
pub fn parens_around_node<'a, 'b: 'a>(
arena: &'a Bump,
item: Spaces<'b, Node<'b>>,
pub fn parens_around_node<'b, 'a: 'b>(
arena: &'b Bump,
item: NodeInfo<'a>,
allow_spaces_before: bool,
) -> Spaces<'a, Node<'a>> {
Spaces {
) -> NodeInfo<'b> {
NodeInfo {
before: if allow_spaces_before {
item.before
} else {
@ -123,11 +123,29 @@ pub fn parens_around_node<'a, 'b: 'a>(
),
// We move the comments/newlines to the outer scope, since they tend to migrate there when re-parsed
after: item.after,
needs_indent: true, // Maybe want to make parens outdentable?
}
}
pub struct NodeInfo<'b> {
pub before: &'b [CommentOrNewline<'b>],
pub item: Node<'b>,
pub after: &'b [CommentOrNewline<'b>],
pub needs_indent: bool,
}
impl<'b> NodeInfo<'b> {
pub fn item(text: Node<'b>) -> NodeInfo<'b> {
NodeInfo {
before: &[],
item: text,
after: &[],
needs_indent: true,
}
}
}
pub trait Nodify<'a> {
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> Spaces<'b, Node<'b>>
fn to_node<'b>(&'a self, arena: &'b Bump, parens: Parens) -> NodeInfo<'b>
where
'a: 'b;
}

View file

@ -2,7 +2,7 @@ use crate::annotation::{Formattable, Newlines, Parens};
use crate::expr::{
expr_is_multiline, expr_lift_spaces_after, fmt_str_literal, format_sq_literal, is_str_multiline,
};
use crate::node::{parens_around_node, Node, NodeSequenceBuilder, Sp};
use crate::node::{parens_around_node, Node, NodeInfo, NodeSequenceBuilder, Sp};
use crate::spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
use crate::Buf;
use bumpalo::Bump;
@ -552,7 +552,7 @@ pub fn pattern_apply_to_node<'b, 'a: 'b>(
parens: Parens,
func: Pattern<'a>,
args: &[Loc<Pattern<'a>>],
) -> Spaces<'b, Node<'b>> {
) -> NodeInfo<'b> {
let func_lifted = pattern_lift_spaces(arena, &func);
let mut b = NodeSequenceBuilder::new(arena, Node::Pattern(func_lifted.item), args.len(), true);
@ -567,10 +567,11 @@ pub fn pattern_apply_to_node<'b, 'a: 'b>(
last_after = arg_lifted.after;
}
let item = Spaces {
let item = NodeInfo {
before: func_lifted.before,
item: b.build(),
after: last_after,
needs_indent: true,
};
let parens = !args.is_empty() && parens == Parens::InApply;