Skip to content

Commit d5393a8

Browse files
committed
WIP Faster array recast
1 parent d8a4ac7 commit d5393a8

File tree

1 file changed

+48
-46
lines changed

1 file changed

+48
-46
lines changed

rust/kcl-lib/src/unparser.rs

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -552,73 +552,61 @@ impl TagDeclarator {
552552

553553
impl ArrayExpression {
554554
fn recast(&self, buf: &mut String, options: &FormatOptions, indentation_level: usize, ctxt: ExprContext) {
555-
// Reconstruct the order of items in the array.
556-
// An item can be an element (i.e. an expression for a KCL value),
557-
// or a non-code item (e.g. a comment)
558555
let num_items = self.elements.len() + self.non_code_meta.non_code_nodes_len();
559556
let mut elems = self.elements.iter();
557+
let mut items_buf = String::with_capacity(512);
558+
let mut item_spans = Vec::with_capacity(num_items);
560559
let mut found_line_comment = false;
561-
let mut format_items: Vec<_> = Vec::with_capacity(num_items);
560+
562561
for i in 0..num_items {
562+
let start = items_buf.len();
563563
if let Some(noncode) = self.non_code_meta.non_code_nodes.get(&i) {
564-
format_items.extend(noncode.iter().map(|nc| {
564+
for nc in noncode {
565565
found_line_comment |= nc.value.should_cause_array_newline();
566-
nc.recast(options, 0)
567-
}));
566+
items_buf.push_str(&nc.recast(options, 0));
567+
}
568568
} else {
569569
let el = elems.next().unwrap();
570-
let mut s = String::with_capacity(256);
571-
el.recast(&mut s, options, 0, ExprContext::Other);
572-
s.push_str(", ");
573-
format_items.push(s);
574-
}
575-
}
576-
577-
// Format these items into a one-line array.
578-
if let Some(item) = format_items.last_mut() {
579-
if let Some(norm) = item.strip_suffix(", ") {
580-
*item = norm.to_owned();
570+
el.recast(&mut items_buf, options, 0, ExprContext::Other);
571+
items_buf.push_str(", ");
581572
}
573+
let end = items_buf.len();
574+
item_spans.push((start, end));
582575
}
583-
let mut flat_recast = String::with_capacity(256);
584-
flat_recast.push('[');
585-
for fi in &format_items {
586-
flat_recast.push_str(fi)
587-
}
588-
flat_recast.push(']');
589576

590-
// We might keep the one-line representation, if it's short enough.
591577
let max_array_length = 40;
592-
let multi_line = flat_recast.len() > max_array_length || found_line_comment;
593-
if !multi_line {
594-
buf.push_str(&flat_recast);
578+
let flat_length = items_buf.trim_end_matches(", ").len();
579+
let use_flat = flat_length <= max_array_length && !found_line_comment;
580+
581+
if use_flat {
582+
buf.push('[');
583+
buf.push_str(&items_buf[..flat_length]);
584+
buf.push(']');
595585
return;
596586
}
597587

598-
// Otherwise, we format a multi-line representation.
588+
// Multi-line representation
599589
buf.push_str("[\n");
600-
let inner_indentation = if ctxt == ExprContext::Pipe {
601-
options.get_indentation_offset_pipe(indentation_level + 1)
602-
} else {
603-
options.get_indentation(indentation_level + 1)
590+
let indent_inner = match ctxt {
591+
ExprContext::Pipe => options.get_indentation_offset_pipe(indentation_level + 1),
592+
_ => options.get_indentation(indentation_level + 1),
604593
};
605-
for format_item in format_items {
606-
buf.push_str(&inner_indentation);
607-
buf.push_str(if let Some(x) = format_item.strip_suffix(" ") {
608-
x
594+
let n = item_spans.len();
595+
for (i, (start, end)) in item_spans.iter().enumerate() {
596+
buf.push_str(&indent_inner);
597+
let s = items_buf[*start..*end].trim_end();
598+
if i < n - 1 {
599+
buf.push_str(s);
609600
} else {
610-
&format_item
611-
});
612-
if !format_item.ends_with('\n') {
613-
buf.push('\n')
601+
buf.push_str(s.trim_matches(','))
614602
}
603+
buf.push('\n');
615604
}
616-
let end_indent = if ctxt == ExprContext::Pipe {
617-
options.get_indentation_offset_pipe(indentation_level)
618-
} else {
619-
options.get_indentation(indentation_level)
605+
let indent_end = match ctxt {
606+
ExprContext::Pipe => options.get_indentation_offset_pipe(indentation_level),
607+
_ => options.get_indentation(indentation_level),
620608
};
621-
buf.push_str(&end_indent);
609+
buf.push_str(&indent_end);
622610
buf.push(']');
623611
}
624612
}
@@ -2998,4 +2986,18 @@ fn function001() {
29982986
let expected = code;
29992987
assert_eq!(recasted, expected);
30002988
}
2989+
2990+
#[test]
2991+
fn check_arr() {
2992+
let code = "[
2993+
-0.8111463382182231,
2994+
-0.41814807547140576,
2995+
]
2996+
";
2997+
2998+
let ast = crate::parsing::top_level_parse(code).unwrap();
2999+
let recasted = ast.recast_top(&FormatOptions::new(), 0);
3000+
let expected = code;
3001+
assert_eq!(recasted, expected);
3002+
}
30013003
}

0 commit comments

Comments
 (0)