Skip to content

Commit ee6207c

Browse files
committed
ast unit testing added
1 parent 0596fe6 commit ee6207c

4 files changed

Lines changed: 125 additions & 40 deletions

File tree

src/ast.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,55 @@ impl ParsedSqlFileSet {
8080
&self.files
8181
}
8282
}
83+
84+
#[cfg(test)]
85+
mod tests {
86+
use super::*;
87+
use std::{env, fs};
88+
use crate::files::{SqlFile, SqlFileSet};
89+
90+
#[test]
91+
fn parsed_sql_file_parses_single_statement() {
92+
let base = env::temp_dir().join("parsed_sql_file_single_stmt_test");
93+
let _ = fs::remove_dir_all(&base);
94+
fs::create_dir_all(&base).unwrap();
95+
let file_path = base.join("one.sql");
96+
let sql = "CREATE TABLE users (id INTEGER PRIMARY KEY);";
97+
fs::write(&file_path, sql).unwrap();
98+
let sql_file = SqlFile::new(&file_path).unwrap();
99+
let parsed = ParsedSqlFile::parse(sql_file).unwrap();
100+
assert_eq!(parsed.path(), file_path.as_path());
101+
assert_eq!(parsed.content(), sql);
102+
assert_eq!(parsed.statements().len(), 1);
103+
let _ = fs::remove_dir_all(&base);
104+
}
105+
106+
#[test]
107+
fn parsed_sql_file_set_parses_multiple_files() {
108+
let base = env::temp_dir().join("parsed_sql_file_set_multi_test");
109+
let _ = fs::remove_dir_all(&base);
110+
fs::create_dir_all(&base).unwrap();
111+
let sub = base.join("subdir");
112+
fs::create_dir_all(&sub).unwrap();
113+
let file1 = base.join("one.sql");
114+
let file2 = sub.join("two.sql");
115+
let sql1 = "CREATE TABLE users (id INTEGER PRIMARY KEY);";
116+
let sql2 = "CREATE TABLE posts (id INTEGER PRIMARY KEY);";
117+
fs::write(&file1, sql1).unwrap();
118+
fs::write(&file2, sql2).unwrap();
119+
let set = SqlFileSet::new(&base, None).unwrap();
120+
let parsed_set = ParsedSqlFileSet::parse_all(set).unwrap();
121+
let files = parsed_set.files();
122+
assert_eq!(files.len(), 2);
123+
for parsed in files {
124+
assert_eq!(parsed.statements().len(), 1);
125+
let stmt = &parsed.statements()[0];
126+
match stmt {
127+
Statement::CreateTable { .. } => {}
128+
other => panic!("expected CreateTable, got: {:?}", other),
129+
}
130+
}
131+
132+
let _ = fs::remove_dir_all(&base);
133+
}
134+
}

src/comments.rs

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,13 @@ pub enum CommentKind {
9696
impl CommentKind {
9797
fn comment(&self) -> &str {
9898
match self {
99-
Self::MultiLine(comment) => comment,
100-
Self::SingleLine(comment) => comment,
99+
Self::MultiLine(comment) | Self::SingleLine(comment) => comment,
101100
}
102101
}
103102
}
104103

105104
/// Structure for containing the [`CommentKind`] and the [`Span`] for a comment
106-
#[derive(Debug, PartialEq)]
105+
#[derive(Debug, Eq, PartialEq)]
107106
pub struct Comment {
108107
kind: CommentKind,
109108
span: Span,
@@ -215,7 +214,7 @@ impl CommentWithSpan {
215214
}
216215

217216
/// Structure for holding all comments found in the document
218-
#[derive(Debug, PartialEq)]
217+
#[derive(Debug, Eq, PartialEq)]
219218
pub struct Comments {
220219
comments: Vec<Comment>,
221220
}
@@ -438,6 +437,7 @@ fn multiline_comment_span() {
438437
#[test]
439438
fn parse_comments() {
440439
use std::path::Path;
440+
441441
use crate::{ast::ParsedSqlFileSet, files::SqlFileSet};
442442
let path = Path::new("sql_files");
443443
let set = SqlFileSet::new(path, None).unwrap();
@@ -459,16 +459,13 @@ fn parse_comments() {
459459
"Main body text",
460460
"When the post was created",
461461
];
462-
assert_eq!(expected.len(),parsed_comments.comments().len());
462+
assert_eq!(expected.len(), parsed_comments.comments().len());
463463
parsed_comments
464464
.comments()
465465
.iter()
466466
.enumerate()
467-
.for_each(|(i,c)|
468-
assert_eq!(expected[i],c.kind().comment()));
469-
470-
471-
},
467+
.for_each(|(i, c)| assert_eq!(expected[i], c.kind().comment()));
468+
}
472469
"sql_files/with_multiline_comments.sql" => {
473470
let expected = [
474471
"Users table stores user account information \nmultiline",
@@ -483,13 +480,13 @@ fn parse_comments() {
483480
"Main body text \n multiline",
484481
"When the post was created \n multiline",
485482
];
486-
assert_eq!(expected.len(),parsed_comments.comments().len());
483+
assert_eq!(expected.len(), parsed_comments.comments().len());
487484
parsed_comments
488485
.comments()
489486
.iter()
490487
.enumerate()
491-
.for_each(|(i,c)| assert_eq!(expected[i],c.kind().comment()));
492-
},
488+
.for_each(|(i, c)| assert_eq!(expected[i], c.kind().comment()));
489+
}
493490
"sql_files/with_mixed_comments.sql" => {
494491
let expected = [
495492
"Users table stores user account information",
@@ -504,26 +501,31 @@ fn parse_comments() {
504501
"Main body text",
505502
"When the post was created",
506503
];
507-
assert_eq!(expected.len(),parsed_comments.comments().len());
504+
assert_eq!(expected.len(), parsed_comments.comments().len());
508505
parsed_comments
509506
.comments()
510507
.iter()
511508
.enumerate()
512-
.for_each(|(i,c)| assert_eq!(expected[i],c.kind().comment()));
513-
514-
},
509+
.for_each(|(i, c)| assert_eq!(expected[i], c.kind().comment()));
510+
}
515511
"sql_files/without_comments.sql" => {
516512
assert_eq!(0, parsed_comments.comments.len());
517-
},
518-
_ => unreachable!("This shouldn't be accessible if directory parsed correctly and all test files accounted for"),
513+
}
514+
_ => {
515+
unreachable!(
516+
"This shouldn't be accessible if directory parsed correctly and all test \
517+
files accounted for"
518+
)
519+
}
519520
}
520521
}
521522
}
522523

523524
#[test]
524525
fn single_line_comment_spans_are_correct() {
525526
use std::path::Path;
526-
use crate::{files::SqlFileSet, ast::ParsedSqlFileSet};
527+
528+
use crate::{ast::ParsedSqlFileSet, files::SqlFileSet};
527529
let path = Path::new("sql_files");
528530
let set = SqlFileSet::new(path, None).unwrap();
529531
let parsed_set = ParsedSqlFileSet::parse_all(set).unwrap();
@@ -549,44 +551,32 @@ fn single_line_comment_spans_are_correct() {
549551
);
550552
}
551553

552-
553554
#[test]
554555
fn multiline_comment_spans_are_correct() {
555556
use std::path::Path;
556-
use crate::{files::SqlFileSet, ast::ParsedSqlFileSet};
557+
558+
use crate::{ast::ParsedSqlFileSet, files::SqlFileSet};
557559
let path = Path::new("sql_files");
558560
let set = SqlFileSet::new(path, None).unwrap();
559561
let parsed_set = ParsedSqlFileSet::parse_all(set).unwrap();
560562
let file = parsed_set
561563
.files()
562564
.iter()
563-
.find(|f| {
564-
f.file()
565-
.path()
566-
.to_str()
567-
.unwrap()
568-
.ends_with("with_multiline_comments.sql")
569-
})
565+
.find(|f| f.file().path().to_str().unwrap().ends_with("with_multiline_comments.sql"))
570566
.expect("with_multiline_comments.sql should be present");
571567
let comments = Comments::parse_all_comments_from_file(file).unwrap();
572568
let comments = comments.comments();
573569
assert_eq!(comments.len(), 11);
574570
let first = &comments[0];
575-
assert_eq!(
576-
first.kind().comment(),
577-
"Users table stores user account information \nmultiline"
578-
);
571+
assert_eq!(first.kind().comment(), "Users table stores user account information \nmultiline");
579572
assert_eq!(first.span().start(), &Location::new(0, 0));
580573
assert_eq!(first.span().end().line(), 1);
581574
assert!(
582575
first.span().end().column() > first.span().start().column(),
583576
"end column should be after start column for first multiline comment",
584577
);
585578
let primary_key = &comments[1];
586-
assert_eq!(
587-
primary_key.kind().comment(),
588-
"Primary key \n multiline"
589-
);
579+
assert_eq!(primary_key.kind().comment(), "Primary key \n multiline");
590580
assert_eq!(primary_key.span().start(), &Location::new(3, 4));
591581
assert_eq!(primary_key.span().end().line(), 4);
592582
assert!(

src/docs.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,44 @@
1-
//! Module for parsing sql and comments and returning only comments connected to statements
1+
//! Module for parsing sql and comments and returning only comments connected to
2+
//! statements
3+
use crate::{ast::ParsedSqlFile, comments::Comments};
4+
5+
/// Structure for containing the `name` of the `Column` and an [`Option`] for
6+
/// the comment as a [`String`]
7+
pub struct ColumnDoc {
8+
name: String,
9+
doc: Option<String>,
10+
}
11+
12+
/// Structure for containing the `name` of the `Table`, an [`Option`] for the
13+
/// comment as a [`String`], and a `Vec` of [`ColumnDoc`] contained in the table
14+
pub struct TableDoc {
15+
name: String,
16+
doc: Option<String>,
17+
columns: Vec<ColumnDoc>,
18+
}
19+
20+
/// Structure for containing the docs for every `Table` in an `.sql` file as a
21+
/// `Vec` of [`TableDoc`]
22+
pub struct SqlDocs {
23+
tables: Vec<TableDoc>,
24+
}
25+
26+
impl SqlDocs {
27+
/// Create a new instance of [`SqlDocs`]
28+
#[must_use]
29+
pub fn new(tables: Vec<TableDoc>) -> Self {
30+
Self { tables }
31+
}
32+
33+
/// Builds documentation for sql file by attaching leading comments to tables and columns
34+
#[must_use]
35+
pub fn from_parsed_file(file: &ParsedSqlFile, comments: &Comments) -> Self {
36+
todo!()
37+
}
38+
39+
/// Getter function to get a slice of [`TableDoc`]
40+
#[must_use]
41+
pub fn tables(&self) -> &[TableDoc] {
42+
&self.tables
43+
}
44+
}

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! - [`files`] : discover and load `.sql` files from disk
33
//! - [`ast`] : parse SQL into an AST using `sqlparser`
44
//! - [`comments`] : extract and model comments + spans
5-
pub mod files;
65
pub mod ast;
76
pub mod comments;
8-
pub mod docs;
7+
pub mod docs;
8+
pub mod files;

0 commit comments

Comments
 (0)