Skip to content
Merged
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
4 changes: 1 addition & 3 deletions .vscode/linter.code-snippets
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@
"$2",
" \"#;",
"",
" let file = SourceFile::parse(&sql);",
" let mut linter = Linter::new([Rule::$3]);",
" let errors = linter.lint(file, sql);",
" let errors = lint(sql, Rule::$3);",
" assert_debug_snapshot!(errors);",
"}",

Expand Down
14 changes: 5 additions & 9 deletions crates/squawk_linter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use enum_iterator::all;
pub use ignore::Ignore;
use ignore::find_ignores;
use ignore_index::IgnoreIndex;
use lazy_static::lazy_static;
use rowan::TextRange;
use rowan::TextSize;
use serde::{Deserialize, Serialize};
Expand All @@ -22,6 +21,9 @@ mod visitors;

mod identifier;
mod rules;

#[cfg(test)]
mod test_utils;
use rules::adding_field_with_default;
use rules::adding_foreign_key_constraint;
use rules::adding_not_null_field;
Expand Down Expand Up @@ -278,15 +280,12 @@ impl Violation {
}
}

#[derive(Default)]
pub struct LinterSettings {
pub pg_version: Version,
pub assume_in_transaction: bool,
}

lazy_static! {
static ref DEFAULT_PG_VERSION: Version = Version::new(15, 0, 0);
}

pub struct Linter {
errors: Vec<Violation>,
ignores: Vec<Ignore>,
Expand Down Expand Up @@ -440,10 +439,7 @@ impl Linter {
errors: vec![],
ignores: vec![],
rules: rules.into(),
settings: LinterSettings {
pg_version: *DEFAULT_PG_VERSION,
assume_in_transaction: false,
},
settings: LinterSettings::default(),
}
}
}
59 changes: 16 additions & 43 deletions crates/squawk_linter/src/rules/adding_field_with_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ pub(crate) fn adding_field_with_default(ctx: &mut Linter, parse: &Parse<SourceFi
mod test {
use insta::assert_debug_snapshot;

use crate::{Linter, Rule};
use crate::Rule;
use crate::test_utils::lint;

#[test]
fn docs_example_ok_post_pg_11() {
Expand All @@ -113,9 +114,7 @@ mod test {
ALTER TABLE "core_recipe" ADD COLUMN "foo" integer DEFAULT 10;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -130,9 +129,7 @@ ALTER TABLE "core_recipe" ALTER COLUMN "foo" SET DEFAULT 10;
-- remove nullability
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -143,9 +140,7 @@ ALTER TABLE "core_recipe" ALTER COLUMN "foo" SET DEFAULT 10;
alter table t set logged, add column c integer default uuid();
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -156,9 +151,7 @@ alter table t set logged, add column c integer default uuid();
ALTER TABLE "core_recipe" ADD COLUMN "foo" integer DEFAULT uuid();
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -170,9 +163,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer DEFAULT uuid();
ALTER TABLE "core_recipe" ADD COLUMN "foo" boolean DEFAULT random();
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -184,9 +175,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" boolean DEFAULT random();
ALTER TABLE "core_recipe" ADD COLUMN "foo" boolean DEFAULT true;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -198,9 +187,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" boolean DEFAULT true;
ALTER TABLE "core_recipe" ADD COLUMN "foo" text DEFAULT 'some-str';
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -212,9 +199,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" text DEFAULT 'some-str';
ALTER TABLE "core_recipe" ADD COLUMN "foo" some_enum_type DEFAULT 'my-enum-variant';
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -226,9 +211,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" some_enum_type DEFAULT 'my-enum-varia
ALTER TABLE "core_recipe" ADD COLUMN "foo" jsonb DEFAULT '{}'::jsonb;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -240,9 +223,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" jsonb DEFAULT '{}'::jsonb;
ALTER TABLE "core_recipe" ADD COLUMN "foo" jsonb DEFAULT myjsonb();
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -254,9 +235,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" jsonb DEFAULT myjsonb();
ALTER TABLE "core_recipe" ADD COLUMN "foo" timestamptz DEFAULT now(123);
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -267,9 +246,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" timestamptz DEFAULT now(123);
ALTER TABLE "core_recipe" ADD COLUMN "foo" timestamptz DEFAULT now();
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -281,9 +258,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" timestamptz DEFAULT now();
alter table account_metadata add column blah integer default 2 + 2;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert_debug_snapshot!(errors);
}

Expand All @@ -294,9 +269,7 @@ ALTER TABLE foo
ADD COLUMN bar numeric GENERATED ALWAYS AS (bar + baz) STORED;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingFieldWithDefault]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingFieldWithDefault);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand Down
19 changes: 6 additions & 13 deletions crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ pub(crate) fn adding_foreign_key_constraint(ctx: &mut Linter, parse: &Parse<Sour

#[cfg(test)]
mod test {
use crate::{Linter, Rule};
use crate::Rule;
use crate::test_utils::lint;

#[test]
fn create_table_with_foreign_key_constraint() {
Expand All @@ -77,9 +78,7 @@ mod test {
COMMIT;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingForeignKeyConstraint]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingForeignKeyConstraint);
assert!(errors.is_empty());
}

Expand All @@ -93,9 +92,7 @@ ALTER TABLE "email" VALIDATE CONSTRAINT "fk_user";
COMMIT;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingForeignKeyConstraint]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingForeignKeyConstraint);
assert!(errors.is_empty());
}

Expand All @@ -108,9 +105,7 @@ ALTER TABLE "email" ADD CONSTRAINT "fk_user" FOREIGN KEY ("user_id") REFERENCES
COMMIT;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingForeignKeyConstraint]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingForeignKeyConstraint);
assert_eq!(errors.len(), 1);
assert_eq!(errors[0].code, Rule::AddingForeignKeyConstraint);
}
Expand All @@ -123,9 +118,7 @@ ALTER TABLE "emails" ADD COLUMN "user_id" INT REFERENCES "user" ("id");
COMMIT;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingForeignKeyConstraint]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingForeignKeyConstraint);
assert_eq!(errors.len(), 1);
assert_eq!(errors[0].code, Rule::AddingForeignKeyConstraint);
}
Expand Down
23 changes: 7 additions & 16 deletions crates/squawk_linter/src/rules/adding_not_null_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,15 @@ pub(crate) fn adding_not_null_field(ctx: &mut Linter, parse: &Parse<SourceFile>)
mod test {
use insta::assert_debug_snapshot;

use crate::{Linter, Rule};
use crate::Rule;
use crate::test_utils::lint;

#[test]
fn set_not_null() {
let sql = r#"
ALTER TABLE "core_recipe" ALTER COLUMN "foo" SET NOT NULL;
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingNotNullableField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingNotNullableField);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -59,9 +58,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer DEFAULT 10 NOT NULL;
ALTER TABLE "core_recipe" ALTER COLUMN "foo" DROP DEFAULT;
COMMIT;
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingNotNullableField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingNotNullableField);
assert!(errors.is_empty());
}

Expand All @@ -71,9 +68,7 @@ COMMIT;
-- This won't work if the table is populated, but that error is caught by adding-required-field.
ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL;
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingNotNullableField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingNotNullableField);
assert!(errors.is_empty());
}

Expand All @@ -87,9 +82,7 @@ BEGIN;
ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL DEFAULT 10;
COMMIT;
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingNotNullableField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingNotNullableField);
assert!(errors.is_empty());
}

Expand All @@ -102,9 +95,7 @@ ALTER TABLE my_table ALTER COLUMN my_column SET NOT NULL;
UPDATE alembic_version SET version_num='b' WHERE alembic_version.version_num = 'a';
COMMIT;
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingNotNullableField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingNotNullableField);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand Down
15 changes: 5 additions & 10 deletions crates/squawk_linter/src/rules/adding_primary_key_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,15 @@ pub(crate) fn adding_primary_key_constraint(ctx: &mut Linter, parse: &Parse<Sour
mod test {
use insta::assert_debug_snapshot;

use crate::{Linter, Rule};
use crate::Rule;
use crate::test_utils::lint;

#[test]
fn serial_primary_key() {
let sql = r#"
ALTER TABLE a ADD COLUMN b SERIAL PRIMARY KEY;
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingSerialPrimaryKeyField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingSerialPrimaryKeyField);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -73,9 +72,7 @@ mod test {
let sql = r#"
ALTER TABLE items ADD PRIMARY KEY (id);
"#;
let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingSerialPrimaryKeyField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingSerialPrimaryKeyField);
assert!(!errors.is_empty());
assert_debug_snapshot!(errors);
}
Expand All @@ -86,9 +83,7 @@ ALTER TABLE items ADD PRIMARY KEY (id);
ALTER TABLE items ADD CONSTRAINT items_pk PRIMARY KEY USING INDEX items_pk;
"#;

let file = squawk_syntax::SourceFile::parse(sql);
let mut linter = Linter::from([Rule::AddingSerialPrimaryKeyField]);
let errors = linter.lint(file, sql);
let errors = lint(sql, Rule::AddingSerialPrimaryKeyField);
assert!(errors.is_empty());
}
}
Loading
Loading