git.delta.rocks / jrsonnet / refs/commits / dacee201fa00

difftreelog

feat(fmt) preserve comments in locals

Yaroslav Bolyukin2023-09-04parent: #016538a.patch.diff
in: master

3 files changed

modifiedcmds/jrsonnet-fmt/src/children.rsdiffbeforeafterboth
40 }40 }
41 let mut iter = node.children_with_tokens().peekable();41 let mut iter = node.children_with_tokens().peekable();
42 while iter.peek() != start {42 while iter.peek() != start {
43 // println!("Skipped {}");
44 dbg!(&iter.next());43 iter.next();
45 }44 }
46 dbg!(&iter.next());45 iter.next();
47 let mut out = Vec::new();46 let mut out = Vec::new();
48 for item in iter {47 for item in iter {
49 if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {48 if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {
59 out58 out
60}59}
60
61pub fn trivia_between(
62 node: SyntaxNode,
63 start: Option<&SyntaxElement>,
64 end: Option<&SyntaxElement>,
65) -> ChildTrivia {
66 let mut iter = node.children_with_tokens().peekable();
67 while iter.peek() != start {
68 iter.next();
69 }
70 iter.next();
71
72 let loose = start.is_none() || end.is_none();
73
74 let mut out = Vec::new();
75 for item in iter.take_while(|i| Some(i) != end) {
76 if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {
77 out.push(trivia);
78 } else if loose {
79 break;
80 } else {
81 assert!(
82 TS![, ;].contains(item.kind()) || item.kind() == ERROR,
83 "silently eaten token: {:?}",
84 item.kind()
85 )
86 }
87 }
88 out
89}
6190
62pub fn children_between<T: AstNode + Debug>(91pub fn children_between<T: AstNode + Debug>(
63 node: SyntaxNode,92 node: SyntaxNode,
modifiedcmds/jrsonnet-fmt/src/comments.rsdiffbeforeafterboth
12 EndOfItems,12 EndOfItems,
13}13}
1414
15#[must_use]
15pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation) -> PrintItems {16pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation) -> PrintItems {
16 let mut pi = p!(new:);17 let mut pi = p!(new:);
1718
modifiedcmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth
13};13};
1414
15use crate::{15use crate::{
16 children::{should_start_with_newline, trivia_after},16 children::{should_start_with_newline, trivia_after, trivia_between},
17 comments::{format_comments, CommentLocation},17 comments::{format_comments, CommentLocation},
18};18};
1919
436 }436 }
437 Expr::ExprVar(n) => p!(new: {n.name()}),437 Expr::ExprVar(n) => p!(new: {n.name()}),
438 Expr::ExprLocal(l) => {438 Expr::ExprLocal(l) => {
439 let mut pi = p!(new: str("local") >i nl);439 let mut pi = p!(new:);
440 let (binds, end_comments) = children_between::<Bind>(
441 l.syntax().clone(),
442 l.local_kw_token().map(Into::into).as_ref(),
443 l.semi_token().map(Into::into).as_ref(),
444 );
445 if binds.len() == 1 {
446 let bind = &binds[0];
447 p!(pi: items(format_comments(&bind.before_trivia, CommentLocation::AboveItem)));
448 p!(pi: str("local ") {bind.value});
449 // TODO: keep end_comments, child.inline_trivia somehow, force multiple locals formatting in case of presence?
450 } else {
451 p!(pi: str("local") >i nl);
440 for bind in l.binds() {452 for bind in binds {
453 if bind.needs_newline_above() {
454 p!(pi: nl);
455 }
456 p!(pi: items(format_comments(&bind.before_trivia, CommentLocation::AboveItem)));
441 p!(pi: {bind} str(",") nl);457 p!(pi: {bind.value} str(";"));
442 }458 p!(pi: items(format_comments(&bind.inline_trivia, CommentLocation::ItemInline)) nl);
459 }
460 // TODO: needs_newline_above end_comments
461 p!(pi: items(format_comments(&end_comments, CommentLocation::EndOfItems)));
462 p!(pi: <i);
463 }
464 p!(pi: str(";") nl);
465
466 let expr_comments = trivia_between(
467 l.syntax().clone(),
468 l.semi_token().map(Into::into).as_ref(),
469 l.expr()
470 .map(|e| e.syntax().clone())
471 .map(Into::into)
472 .as_ref(),
473 );
474 p!(pi: items(format_comments(&expr_comments, CommentLocation::AboveItem)));
475
476 // TODO: needs_newline_above expr
443 p!(pi: <i str(";") nl {l.expr()});477 p!(pi: {l.expr()});
444 pi478 pi
445 }479 }
446 Expr::ExprIfThenElse(ite) => {480 Expr::ExprIfThenElse(ite) => {
487521
488fn main() {522fn main() {
489 let (parsed, _errors) = jrsonnet_rowan_parser::parse(523 let (parsed, _errors) = jrsonnet_rowan_parser::parse(
490 r#"524 r#"
491525
492526
493 # Edit me!527 # Edit me!
494 local b = import "b.libsonnet"; # comment528 local b = import "b.libsonnet"; # comment
495 local a = import "a.libsonnet";529 local a = import "a.libsonnet";
496530
497 local f(x,y)=x+y;531 local f(x,y)=x+y;
498532
499 local {a: [b, ..., c], d, ...e} = null;533 local {a: [b, ..., c], d, ...e} = null;
500534
501 local ass = assert false : false; false;535 local ass = assert false : false; false;
502536
503 local fn = function(a, b, c = 3) 4;537 local fn = function(a, b, c = 3) 4;
504538
505 local comp = [a for b in c if d == e];539 local comp = [a for b in c if d == e];
506 local ocomp = {[k]: 1 for k in v};540 local ocomp = {[k]: 1 for k in v};
507541
508 local ? = skip;542 local ? = skip;
509543
510 local intr = $intrinsic(test);544 local intr = $intrinsic(test);
511 local intrId = $intrinsicId;545 local intrId = $intrinsicId;
512 local intrThisFile = $intrinsicThisFile;546 local intrThisFile = $intrinsicThisFile;
513547
514 local ie = a[expr];548 local ie = a[expr];
515549
516 local unary = !a;550 local unary = !a;
517551
518 local Template = {z: "foo"};552 local
553 // I am comment
554 singleLocalWithItemComment = 1,
555 ;
556
557 // Comment between local and expression
558
559 local
560 a = 1, // Inline
561 // Comment above b
562 b = 4,
563
564 // c needs some space
565 c = 5,
566
567 // Comment after everything
568 ;
569
570
571 local Template = {z: "foo"};
519572
520 {573 {
521 local574 local
522575
523 h = 3,576 h = 3,
524 assert self.a == 1577 assert self.a == 1
525578
526 : "error",579 : "error",
527 "f": ((((((3)))))) ,580 "f": ((((((3)))))) ,
528 "g g":581 "g g":
529 f(4,2),582 f(4,2),
530 arr: [[583 arr: [[
531 1, 2,584 1, 2,
532 ],585 ],
533 3,586 3,
534 {587 {
535 b: {588 b: {
536 c: {589 c: {
537 k: [16]590 k: [16]
538 }591 }
539 }592 }
540 }593 }
541 ],594 ],
542 m: a[1::],595 m: a[1::],
543 m: b[::],596 m: b[::],
544597
545 comments: {598 comments: {
546 _: '',599 _: '',
547 // Plain comment600 // Plain comment
548 a: '',601 a: '',
549602
550 # Plain comment with empty line before603 # Plain comment with empty line before
551 b: '',604 b: '',
552 /*Single-line multiline comment605 /*Single-line multiline comment
553606
554 */607 */
555 c: '',608 c: '',
556609
557 /**Single-line multiline doc comment610 /**Single-line multiline doc comment
558611
559 */612 */
560 c: '',613 c: '',
561614
562 /**multiline doc comment615 /**multiline doc comment
563 s616 s
564 */617 */
565 c: '',618 c: '',
566619
567 /*620 /*
568621
569 Multi-line622 Multi-line
570623
571 comment624 comment
572 */625 */
573 d: '',626 d: '',
574627
575 e: '', // Inline comment628 e: '', // Inline comment
576629
577 k: '',630 k: '',
578631
579 // Text after everything632 // Text after everything
580 },633 },
581 comments2: {634 comments2: {
582 k: '',635 k: '',
583 // Text after everything, but no newline above636 // Text after everything, but no newline above
584 },637 },
585 k: if a == b then638 k: if a == b then
586639
587640
588 2641 2
589642
590 else Template {}643 else Template {}
591 } + Template644 } + Template
592645
593646
594 // Comment after everything647 // Comment after everything
595"#,648"#,
596 );649 );
597650
598 // dbg!(errors);651 // dbg!(errors);