Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

162 changes: 1 addition & 161 deletions crates/squawk/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,13 @@
use anyhow::{Context, Result};
use log::info;
use serde::Deserialize;
use squawk_linter::config::{ConfigFile, UploadToGitHubConfig};
use squawk_linter::{Rule, Version};
use std::{
env,
io::{self, IsTerminal},
path::{Path, PathBuf},
process,
};

use crate::{Command, DebugOption, Opts, Reporter, UploadToGithubArgs};

const FILE_NAME: &str = ".squawk.toml";

#[derive(Debug, Default, Deserialize)]
pub struct UploadToGitHubConfig {
#[serde(default)]
pub fail_on_violations: Option<bool>,
}

#[derive(Debug, Default, Deserialize)]
pub struct ConfigFile {
#[serde(default)]
pub excluded_paths: Vec<String>,
#[serde(default)]
pub excluded_rules: Vec<Rule>,
#[serde(default)]
pub included_rules: Vec<Rule>,
#[serde(default)]
pub pg_version: Option<Version>,
#[serde(default)]
pub assume_in_transaction: Option<bool>,
#[serde(default)]
pub upload_to_github: UploadToGitHubConfig,
}

impl ConfigFile {
pub fn parse(custom_path: Option<PathBuf>) -> Result<Option<Self>> {
let path = if let Some(path) = custom_path {
Some(path)
} else {
find_by_traversing_back()?
};

if let Some(p) = path {
info!("using config file path: {}", p.display());

let file_content = std::fs::read_to_string(p)?;
return Ok(Some(toml::from_str(&file_content)?));
}

info!("no config file found");
Ok(None)
}
}

pub struct Config {
pub excluded_paths: Vec<String>,
pub excluded_rules: Vec<Rule>,
Expand Down Expand Up @@ -165,116 +118,3 @@ impl Config {
}
}
}

fn recurse_directory(directory: &Path, file_name: &str) -> Result<Option<PathBuf>, std::io::Error> {
for entry in directory.read_dir()? {
let entry = entry?;
if entry.file_name() == file_name {
return Ok(Some(entry.path()));
}
}
if let Some(parent) = directory.parent() {
recurse_directory(parent, file_name)
} else {
Ok(None)
}
}

fn find_by_traversing_back() -> Result<Option<PathBuf>> {
recurse_directory(&env::current_dir()?, FILE_NAME)
.context("Error when finding configuration file")
}

#[cfg(test)]
mod test_config {
use std::fs;
use tempfile::NamedTempFile;

use insta::assert_debug_snapshot;

use super::*;

#[test]
fn load_cfg_full() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r#"
pg_version = "19.1"
excluded_paths = ["example.sql"]
excluded_rules = ["require-concurrent-index-creation"]
assume_in_transaction = true

"#;
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_pg_version() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r#"
pg_version = "19.1"

"#;
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_excluded_rules() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r#"
excluded_rules = ["require-concurrent-index-creation"]

"#;
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_excluded_paths() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r#"
excluded_paths = ["example.sql"]

"#;
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_assume_in_transaction() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r"
assume_in_transaction = false

";
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_fail_on_violations() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r"
[upload_to_github]
fail_on_violations = true
";
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_included_rules() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r#"
included_rules = ["require-table-schema"]

"#;
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
#[test]
fn load_excluded_rules_with_alias() {
let squawk_toml = NamedTempFile::new().expect("generate tempFile");
let file = r#"
excluded_rules = ["prefer-timestamp-tz", "prefer-timestamptz"]

"#;
fs::write(&squawk_toml, file).expect("Unable to write file");
assert_debug_snapshot!(ConfigFile::parse(Some(squawk_toml.path().to_path_buf())));
}
}
19 changes: 3 additions & 16 deletions crates/squawk_fmt/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,14 +422,11 @@ fn build_type<'a>(ty: ast::Type) -> Doc<'a> {
fn leading_comments_token<'a>(node: &SyntaxToken) -> Doc<'a> {
let mut doc = Doc::nil();
for next in node.siblings_with_tokens(Direction::Prev).skip(1) {
println!("prev");
match next {
rowan::NodeOrToken::Node(node) => {
println!("before node {:?}", node);
rowan::NodeOrToken::Node(_) => {
break;
}
rowan::NodeOrToken::Token(token) => {
println!("before token {:?}", token);
if token.kind() == SyntaxKind::COMMENT {
doc = doc
.append(Doc::text(token.text().to_string()))
Expand All @@ -448,14 +445,11 @@ fn leading_comments_token<'a>(node: &SyntaxToken) -> Doc<'a> {
fn leading_comments<'a>(node: &SyntaxNode) -> Doc<'a> {
let mut doc = Doc::nil();
for next in node.siblings_with_tokens(Direction::Prev).skip(1) {
println!("prev");
match next {
rowan::NodeOrToken::Node(node) => {
println!("before node {:?}", node);
rowan::NodeOrToken::Node(_) => {
break;
}
rowan::NodeOrToken::Token(token) => {
println!("before token {:?}", token);
if token.kind() == SyntaxKind::COMMENT {
let is_block = token.text().starts_with("--");
doc = doc
Expand All @@ -479,14 +473,11 @@ fn leading_comments<'a>(node: &SyntaxNode) -> Doc<'a> {
fn trailing_comments<'a>(node: &SyntaxNode) -> Doc<'a> {
let mut doc = Doc::nil();
for next in node.siblings_with_tokens(Direction::Next).skip(1) {
println!("after");
match next {
rowan::NodeOrToken::Node(node) => {
println!("after node {:?}", node);
rowan::NodeOrToken::Node(_) => {
break;
}
rowan::NodeOrToken::Token(token) => {
println!("after token {:?}", token);
if token.kind() == SyntaxKind::COMMENT {
doc = doc
.append(Doc::space())
Expand Down Expand Up @@ -532,10 +523,6 @@ fn build_target<'a>(target: ast::Target) -> Option<Doc<'a>> {
pub fn fmt(text: &str) -> String {
let parse = ast::SourceFile::parse(text);
let file = parse.tree();
println!("{}", text);
println!("---");
println!("{:#?}", file.syntax());
println!("---");
debug_assert_eq!(
parse.errors(),
vec![],
Expand Down
4 changes: 4 additions & 0 deletions crates/squawk_linter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ line-index.workspace = true
serde_plain.workspace = true
annotate-snippets.workspace = true
rustc-hash.workspace = true
toml.workspace = true
anyhow.workspace = true
log.workspace = true

[dev-dependencies]
tempfile.workspace = true
insta.workspace = true

[lints]
Expand Down
Loading
Loading