Skip to content

Commit 5b3a109

Browse files
committed
Multiline flattening now handled at correct layer; Fixes #23
1 parent 1a1087a commit 5b3a109

File tree

3 files changed

+206
-192
lines changed

3 files changed

+206
-192
lines changed

src/comments.rs

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -389,12 +389,17 @@ impl Comments {
389389

390390
/// Collapse this collection of comments and separate each comment with `\n` as a single [`Comment`].
391391
#[must_use]
392-
pub fn collapse_comments(self) -> Option<Comment> {
392+
pub fn collapse_comments(self, flatten: MultiFlatten) -> Option<Comment> {
393393
let mut iter = self.comments.into_iter();
394394
let first = iter.next()?;
395395

396396
let Some(second) = iter.next() else {
397-
return Some(first);
397+
let text = first.text();
398+
return Some(Comment::new(
399+
flatten_lines(text, flatten),
400+
first.kind().to_owned(),
401+
first.span().to_owned(),
402+
));
398403
};
399404

400405
let start = *first.span().start();
@@ -411,8 +416,28 @@ impl Comments {
411416
end = *c.span().end();
412417
}
413418

414-
Some(Comment::new(text, CommentKind::MultiLine, Span::new(start, end)))
419+
Some(Comment::new(
420+
flatten_lines(&text, flatten),
421+
CommentKind::MultiLine,
422+
Span::new(start, end),
423+
))
424+
}
425+
}
426+
427+
fn flatten_lines(lines: &str, flatten: MultiFlatten) -> String {
428+
let mut out = String::new();
429+
let sep = match flatten {
430+
MultiFlatten::FlattenWithNone => String::new(),
431+
MultiFlatten::NoFlat => return lines.to_owned(),
432+
MultiFlatten::Flatten(chars) => chars.to_owned(),
433+
};
434+
for (i, line) in lines.lines().enumerate() {
435+
if i > 0 {
436+
out.push_str(&sep);
437+
}
438+
out.push_str(line);
415439
}
440+
out
416441
}
417442

418443
/// Controls how leading comments are captured for a statement.
@@ -427,6 +452,18 @@ pub enum LeadingCommentCapture {
427452
AllSingleOneMulti,
428453
}
429454

455+
/// Enum for multiline comment flattening.
456+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
457+
pub enum MultiFlatten<'a> {
458+
/// Default option, retains multiline structure with `\n`
459+
#[default]
460+
NoFlat,
461+
/// Sets multiline comments to be flattened and combined without adding formatting
462+
FlattenWithNone,
463+
/// Will flatten comments and amend the content of [`String`] to the end of the former leading lines
464+
Flatten(&'a str),
465+
}
466+
430467
#[cfg(test)]
431468
mod tests {
432469
use std::{env, fs};
@@ -937,7 +974,7 @@ CREATE TABLE t (id INTEGER);
937974
#[test]
938975
fn collapse_comments_empty_returns_none() {
939976
let comments = Comments::new(vec![]);
940-
assert!(comments.collapse_comments().is_none());
977+
assert!(comments.collapse_comments(crate::comments::MultiFlatten::NoFlat).is_none());
941978
}
942979

943980
#[test]
@@ -949,8 +986,9 @@ CREATE TABLE t (id INTEGER);
949986
);
950987
let comments = Comments::new(vec![c]);
951988

952-
let collapsed =
953-
comments.collapse_comments().unwrap_or_else(|| panic!("should return a comment"));
989+
let collapsed = comments
990+
.collapse_comments(crate::comments::MultiFlatten::NoFlat)
991+
.unwrap_or_else(|| panic!("should return a comment"));
954992
assert_eq!(collapsed.text(), "solo");
955993
assert_eq!(collapsed.kind(), &CommentKind::SingleLine);
956994
assert_eq!(collapsed.span(), &Span::new(Location::new(10, 3), Location::new(10, 11)));
@@ -976,7 +1014,9 @@ CREATE TABLE t (id INTEGER);
9761014

9771015
let comments = Comments::new(vec![c1, c2, c3]);
9781016

979-
let collapsed = comments.collapse_comments().unwrap_or_else(|| panic!("should collapse"));
1017+
let collapsed = comments
1018+
.collapse_comments(crate::comments::MultiFlatten::NoFlat)
1019+
.unwrap_or_else(|| panic!("should collapse"));
9801020
assert_eq!(collapsed.text(), "a\nb\nc");
9811021
assert_eq!(collapsed.kind(), &CommentKind::MultiLine);
9821022
assert_eq!(collapsed.span(), &Span::new(Location::new(1, 1), Location::new(4, 3)));
@@ -995,7 +1035,9 @@ CREATE TABLE t (id INTEGER);
9951035
let leading = parsed.leading_comments(3, LeadingCommentCapture::AllLeading);
9961036
assert_eq!(texts(&leading), vec!["c1".to_owned(), "c2".to_owned()]);
9971037

998-
let collapsed = leading.collapse_comments().unwrap_or_else(|| panic!("should collapse"));
1038+
let collapsed = leading
1039+
.collapse_comments(crate::comments::MultiFlatten::NoFlat)
1040+
.unwrap_or_else(|| panic!("should collapse"));
9991041
assert_eq!(collapsed.text(), "c1\nc2");
10001042
assert_eq!(collapsed.kind(), &CommentKind::MultiLine);
10011043

@@ -1018,10 +1060,23 @@ CREATE TABLE t (id INTEGER);
10181060
let leading = parsed.leading_comments(3, LeadingCommentCapture::SingleNearest);
10191061
assert_eq!(texts(&leading), vec!["c2".to_owned()]);
10201062

1021-
let collapsed = leading.collapse_comments().unwrap_or_else(|| panic!("should collapse"));
1063+
let collapsed = leading
1064+
.collapse_comments(crate::comments::MultiFlatten::NoFlat)
1065+
.unwrap_or_else(|| panic!("should collapse"));
10221066
assert_eq!(collapsed.text(), "c2");
10231067
assert_eq!(collapsed.kind(), &CommentKind::SingleLine);
10241068

10251069
Ok(())
10261070
}
1071+
use crate::comments::flatten_lines;
1072+
#[test]
1073+
fn test_flatten_lines_behavior() {
1074+
let input = "a\nb\nc";
1075+
let no_sep = flatten_lines(input, crate::comments::MultiFlatten::FlattenWithNone);
1076+
assert_eq!(no_sep, "abc");
1077+
let dash_sep = flatten_lines(input, crate::comments::MultiFlatten::Flatten(" - "));
1078+
assert_eq!(dash_sep, "a - b - c");
1079+
let single = flatten_lines("solo", crate::comments::MultiFlatten::Flatten("XXX"));
1080+
assert_eq!(single, "solo");
1081+
}
10271082
}

src/docs.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use sqlparser::ast::{Ident, ObjectName, ObjectNamePart, Spanned, Statement};
77

88
use crate::{
99
ast::ParsedSqlFile,
10-
comments::{Comments, LeadingCommentCapture},
10+
comments::{Comments, LeadingCommentCapture, MultiFlatten},
1111
error::DocError,
1212
};
1313

@@ -222,6 +222,7 @@ impl SqlFileDoc {
222222
file: &ParsedSqlFile,
223223
comments: &Comments,
224224
capture: LeadingCommentCapture,
225+
flatten: MultiFlatten,
225226
) -> Result<Self, DocError> {
226227
let mut tables = Vec::new();
227228
for statement in file.statements() {
@@ -232,8 +233,9 @@ impl SqlFileDoc {
232233
let mut column_docs = Vec::new();
233234
for column in &table.columns {
234235
let column_start = column.span().start.line;
235-
let column_leading =
236-
comments.leading_comments(column_start, capture).collapse_comments();
236+
let column_leading = comments
237+
.leading_comments(column_start, capture)
238+
.collapse_comments(flatten);
237239
let column_name = column.name.value.clone();
238240
let column_doc = match column_leading {
239241
Some(col_comment) => {
@@ -243,7 +245,8 @@ impl SqlFileDoc {
243245
};
244246
column_docs.push(column_doc);
245247
}
246-
let table_leading = comments.leading_comment(table_start);
248+
let table_leading =
249+
comments.leading_comments(table_start, capture).collapse_comments(flatten);
247250
let (schema, name) = schema_and_table(&table.name)?;
248251
let table_doc = TableDoc::new(
249252
schema,
@@ -504,7 +507,12 @@ CREATE TABLE posts (
504507

505508
for file in parsed_set.files() {
506509
let comments = Comments::parse_all_comments_from_file(file)?;
507-
let docs = SqlFileDoc::from_parsed_file(file, &comments, capture);
510+
let docs = SqlFileDoc::from_parsed_file(
511+
file,
512+
&comments,
513+
capture,
514+
crate::comments::MultiFlatten::NoFlat,
515+
);
508516
let filename = file
509517
.file()
510518
.path()

0 commit comments

Comments
 (0)