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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ The project uses a modular Rust workspace with crates prefixed with `pgls_`:
- `pgls_text_edit` - Text manipulation utilities
- `pgls_line_index` - Converts offsets to line/column positions in UTF-8, UTF-16 or UTF-32 and back, and the character positions that Postgres reports to offsets. Convert positions with it, not by hand
- `pgls_suppressions` - Rule suppression handling
- `pgls_migrations` - Migration tools (Supabase, dbmate, goose): migration files and versions, up/down sections, project detection for `init`

### TypeScript Packages
Located in `packages/`:
Expand Down
4 changes: 4 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ The fallback type check against the database (via `EXPLAIN`), for statements tha

Handles `-- pgls-ignore` style rule suppression comments.

##### `crates/pgls_migrations`

What the language server knows about migration tools (Supabase, dbmate, goose, and plain SQL files). Every tool implements every method of one `MigrationTool` trait, and calls shared helpers for what it does like other tools: which files are migrations and their versions, how a file splits into up and down sections with their transaction mode, the diagnostics for misplaced markers, and how `init` finds the tool's projects. The workspace keeps what the tool of a file's settings says about its text, and the analyser runs each section on its own.

#### Feature crates

##### `crates/pgls_completions`, `crates/pgls_hover`
Expand Down
17 changes: 16 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pgls_line_index = { path = "./crates/pgls_line_index", version = "0.
pgls_lsp = { path = "./crates/pgls_lsp", version = "0.0.0" }
pgls_markup = { path = "./crates/pgls_markup", version = "0.0.0" }
pgls_matcher = { path = "./crates/pgls_matcher", version = "0.0.0" }
pgls_migrations = { path = "./crates/pgls_migrations", version = "0.0.0" }
pgls_pglinter = { path = "./crates/pgls_pglinter", version = "0.0.0" }
pgls_plpgsql_check = { path = "./crates/pgls_plpgsql_check", version = "0.0.0" }
pgls_postgres_regress = { path = "./crates/pgls_postgres_regress", version = "0.0.0" }
Expand Down
1 change: 1 addition & 0 deletions crates/pgls_analyser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pgls_catalog = { workspace = true }
pgls_console = { workspace = true }
pgls_diagnostics = { workspace = true }
pgls_lexer = { workspace = true }
pgls_migrations = { workspace = true }
pgls_query = { workspace = true }
pgls_query_ext = { workspace = true }
pgls_text_size = { workspace = true }
Expand Down
20 changes: 14 additions & 6 deletions crates/pgls_analyser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
use pgls_analyse::{AnalysisFilter, AppliesTo, MetadataRegistry};
use pgls_catalog::{Catalog, CatalogBase, Session, TransactionMode, resolve::FunctionContext};
use pgls_diagnostics::DiagnosticTags;
use pgls_migrations::{Direction, Unit};
use pgls_query_ext::function_body::{EmbeddedStatement, OffsetMap};
use pgls_text_size::{TextRange, TextSize};
pub use registry::visit_registry;
Expand All @@ -16,7 +17,6 @@ mod linter_context;
mod linter_options;
mod linter_registry;
mod linter_rule;
mod migration;
pub mod options;
mod registry;

Expand All @@ -27,7 +27,6 @@ pub use linter_registry::{
LinterRegistryRuleParams, LinterRuleRegistry, LinterRuleRegistryBuilder,
};
pub use linter_rule::{FixEdit, LinterDiagnostic, LinterRule, RuleFix};
pub use migration::{Direction, MigrationSection};

// For convenience in macros and rule files - keep these shorter names
pub use LinterDiagnostic as RuleDiagnostic;
Expand Down Expand Up @@ -166,7 +165,7 @@ pub struct AnalyserParams {
pub file_kind: FileKind,
/// The sections of a migration file, like dbmate's up and down migrations. Each section is
/// analysed as a migration of its own. Without sections, the whole file is one migration.
pub sections: Vec<MigrationSection>,
pub sections: Vec<Unit>,
/// Whether the rules of the typecheck group run.
pub typecheck: bool,
/// The text of the file. Fixes that also edit after their statement, like the `COMMIT` that
Expand Down Expand Up @@ -269,7 +268,7 @@ impl<'a> Analyser<'a> {
// Each section runs in a session and transaction of its own.
let session = Session::new(params.search_path.clone()).with_transaction_mode(
unit.section
.map_or(TransactionMode::Unknown, MigrationSection::transaction_mode),
.map_or(TransactionMode::Unknown, transaction_mode),
);
let stmts = &params.stmts[unit.stmts.clone()];
// The last statement of the unit, including those that don't parse. The statements
Expand Down Expand Up @@ -520,17 +519,26 @@ fn debug_assert_in_statement(diagnostic: &LinterDiagnostic, stmt: &AnalysableSta
}
}

/// The transaction mode that a migration section starts in.
pub fn transaction_mode(section: &Unit) -> TransactionMode {
if section.transaction {
TransactionMode::Transaction
} else {
TransactionMode::Autocommit
}
}

/// Statements that run together: those before the first section marker, then each section.
struct MigrationUnit<'a> {
section: Option<&'a MigrationSection>,
section: Option<&'a Unit>,
/// The indices of the statements.
stmts: Range<usize>,
range: TextRange,
}

fn migration_units<'a>(
stmts: &[AnalysableStatement],
sections: &'a [MigrationSection],
sections: &'a [Unit],
) -> Vec<MigrationUnit<'a>> {
let before_sections = sections
.first()
Expand Down
36 changes: 0 additions & 36 deletions crates/pgls_analyser/src/migration.rs

This file was deleted.

11 changes: 6 additions & 5 deletions crates/pgls_analyser/tests/rules_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use std::{

use pgls_analyse::{AnalysisFilter, Applicability, RuleFilter};
use pgls_analyser::{
AnalysableStatement, Analyser, AnalyserConfig, AnalyserParams, Direction, LinterDiagnostic,
LinterOptions, MigrationSection, RuleFix, UnparsableStatement,
AnalysableStatement, Analyser, AnalyserConfig, AnalyserParams, LinterDiagnostic, LinterOptions,
RuleFix, UnparsableStatement,
};
use pgls_console::StdDisplay;
use pgls_diagnostics::PrintDiagnostic;
use pgls_migrations::{Direction, Unit};
use pgls_text_size::{TextRange, TextSize};

static TYPECHECK_CATALOG: OnceLock<Arc<pgls_catalog::CatalogBase>> = OnceLock::new();
Expand Down Expand Up @@ -229,8 +230,8 @@ fn sql_function_body(
/// The migration sections of the file, each starting at a `-- section: up` or
/// `-- section: down transaction:false` line. Like dbmate, each section is sent to Postgres as
/// one query, unless `queries:separate` follows, like goose without `StatementBegin`.
fn migration_sections(query: &str) -> Vec<MigrationSection> {
let mut sections: Vec<MigrationSection> = Vec::new();
fn migration_sections(query: &str) -> Vec<Unit> {
let mut sections: Vec<Unit> = Vec::new();
let mut one_query = Vec::new();
let mut offset = 0;
for line in query.split_inclusive('\n') {
Expand All @@ -257,7 +258,7 @@ fn migration_sections(query: &str) -> Vec<MigrationSection> {
if let Some(previous) = sections.last_mut() {
previous.range = TextRange::new(previous.range.start(), start);
}
sections.push(MigrationSection {
sections.push(Unit {
range: TextRange::new(start, TextSize::from(query.len() as u32)),
direction,
transaction,
Expand Down
2 changes: 1 addition & 1 deletion crates/pgls_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pgls_env = { workspace = true }
pgls_fs = { workspace = true }
pgls_lexer = { workspace = true }
pgls_lsp = { workspace = true }
pgls_migrations = { workspace = true }
pgls_query = { workspace = true }
pgls_text_edit = { workspace = true }
pgls_workspace = { workspace = true }
Expand All @@ -38,7 +39,6 @@ serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sqlx = { workspace = true }
tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "sync", "rt-multi-thread", "macros"] }
toml = { workspace = true }
tracing = { workspace = true }
tracing-appender = "0.2.3"
tracing-bunyan-formatter = { workspace = true }
Expand Down
Loading
Loading