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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"postgrestools.bin": "./target/debug/postgrestools"
"postgres-language-server.bin": "./target/debug/postgres-language-server"
}
25 changes: 20 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ just new-crate <name>
```

### CLI Usage
The main CLI binary is `postgrestools`:
The main CLI binary is `postgres-language-server` (legacy name: `postgrestools`):
```bash
cargo run -p pgls_cli -- check file.sql
# or after building:
./target/release/postgrestools check file.sql
./target/release/postgres-language-server check file.sql
```

## Architecture
Expand Down Expand Up @@ -103,8 +103,8 @@ The project uses a modular Rust workspace with crates prefixed with `pgls_`:
### TypeScript Packages
Located in `packages/` and `editors/`:
- VSCode extension in `editors/code/`
- Backend JSON-RPC bridge in `packages/@postgrestools/backend-jsonrpc/`
- Main TypeScript package in `packages/@postgrestools/postgrestools/`
- Backend JSON-RPC bridge in `packages/@postgres-language-server/backend-jsonrpc/` (legacy: `packages/@postgrestools/backend-jsonrpc/`)
- Main TypeScript package in `packages/@postgres-language-server/postgres-language-server/` (legacy: `packages/@postgrestools/postgrestools/`)

### Database Integration
The server connects to a Postgres database to build an in-memory schema cache containing tables, columns, functions, and type information. This enables accurate autocompletion and type checking.
Expand Down Expand Up @@ -150,6 +150,21 @@ Many parser structures are generated from PostgreSQL's protobuf definitions usin
### Database Schema
The `pgls_schema_cache` crate contains SQL queries in `src/queries/` that introspect the database schema to build the in-memory cache.

### Multi-Platform Support
### Code Refactoring Tools
The project has `ast-grep` available for advanced code search and refactoring tasks. ast-grep is a structural search/replace tool that understands code syntax, making it useful for:
- Renaming types, functions, or variables across the codebase
- Finding and replacing code patterns
- Performing structural code transformations

Example usage:
```bash
# Search for a pattern
ast-grep --pattern 'struct $NAME { $$$FIELDS }'

# Replace a pattern across files
ast-grep --pattern 'OldType' --rewrite 'NewType' --update-all
```

### Multi-Platform Support
The project includes platform-specific allocators and build configurations for Windows, macOS, and Linux.
- Seeing the Treesitter tree for an SQL query can be helpful to debug and implement features. To do this, create a file with an SQL query, and run `just tree-print <file.sql>`.
26 changes: 13 additions & 13 deletions crates/pgls_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub(crate) mod version;
#[bpaf(options, version(VERSION))]
#[allow(clippy::large_enum_variant)]
/// Postgres Tools official CLI. Use it to check the health of your project or run it to check single files.
pub enum PgtCommand {
pub enum PgLSCommand {
/// Shows the version information and quit.
#[bpaf(command)]
Version(#[bpaf(external(cli_options), hide_usage)] CliOptions),
Expand Down Expand Up @@ -218,19 +218,19 @@ pub enum PgtCommand {
PrintSocket,
}

impl PgtCommand {
impl PgLSCommand {
const fn cli_options(&self) -> Option<&CliOptions> {
match self {
PgtCommand::Version(cli_options)
| PgtCommand::Check { cli_options, .. }
| PgtCommand::Dblint { cli_options, .. } => Some(cli_options),
PgtCommand::LspProxy { .. }
| PgtCommand::Start { .. }
| PgtCommand::Stop
| PgtCommand::Init
| PgtCommand::RunServer { .. }
| PgtCommand::Clean
| PgtCommand::PrintSocket => None,
PgLSCommand::Version(cli_options)
| PgLSCommand::Check { cli_options, .. }
| PgLSCommand::Dblint { cli_options, .. } => Some(cli_options),
PgLSCommand::LspProxy { .. }
| PgLSCommand::Start { .. }
| PgLSCommand::Stop
| PgLSCommand::Init
| PgLSCommand::RunServer { .. }
| PgLSCommand::Clean
| PgLSCommand::PrintSocket => None,
}
}

Expand Down Expand Up @@ -315,6 +315,6 @@ mod tests {
/// Tests that all CLI options adhere to the invariants expected by `bpaf`.
#[test]
fn check_options() {
pgt_command().check_invariants(false);
pg_l_s_command().check_invariants(false);
}
}
4 changes: 2 additions & 2 deletions crates/pgls_cli/src/execute/process_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::execute::config::ExecutionMode;
use crate::execute::walk::TraversalOptions;
use check::check_file;
use pgls_diagnostics::Error;
use pgls_fs::PgTPath;
use pgls_fs::PgLSPath;
use std::marker::PhantomData;
use std::ops::Deref;

Expand Down Expand Up @@ -103,7 +103,7 @@ impl<'ctx, 'app> Deref for SharedTraversalOptions<'ctx, 'app> {
/// diagnostics were emitted, or compare the formatted code with the original
/// content of the file and emit a diff or write the new content to the disk if
/// write mode is enabled
pub(crate) fn process_file(ctx: &TraversalOptions, pgls_path: &PgTPath) -> FileResult {
pub(crate) fn process_file(ctx: &TraversalOptions, pgls_path: &PgLSPath) -> FileResult {
tracing::trace_span!("process_file", path = ?pgls_path).in_scope(move || {
let shared_context = &SharedTraversalOptions::new(ctx);

Expand Down
4 changes: 2 additions & 2 deletions crates/pgls_cli/src/execute/process_file/workspace_file.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::execute::diagnostics::{ResultExt, ResultIoExt};
use crate::execute::process_file::SharedTraversalOptions;
use pgls_diagnostics::{Error, category};
use pgls_fs::{File, OpenOptions, PgTPath};
use pgls_fs::{File, OpenOptions, PgLSPath};
use pgls_workspace::workspace::{FileGuard, OpenFileParams};
use pgls_workspace::{Workspace, WorkspaceError};
use std::path::{Path, PathBuf};
Expand All @@ -24,7 +24,7 @@ impl<'ctx, 'app> WorkspaceFile<'ctx, 'app> {
ctx: &SharedTraversalOptions<'ctx, 'app>,
path: &Path,
) -> Result<Self, Error> {
let pgls_path = PgTPath::new(path);
let pgls_path = PgLSPath::new(path);
let open_options = OpenOptions::default()
.read(true)
.write(ctx.config.allows_writes());
Expand Down
20 changes: 10 additions & 10 deletions crates/pgls_cli/src/execute/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::reporter::{Report, TraversalData};
use crate::{CliDiagnostic, CliSession};
use crossbeam::channel::{Receiver, Sender, unbounded};
use pgls_diagnostics::{DiagnosticExt, Error, Resource};
use pgls_fs::{FileSystem, PathInterner, PgTPath};
use pgls_fs::{FileSystem, PathInterner, PgLSPath};
use pgls_fs::{TraversalContext, TraversalScope};
use pgls_workspace::dome::Dome;
use pgls_workspace::workspace::IsPathIgnoredParams;
Expand Down Expand Up @@ -133,7 +133,7 @@ fn traverse_inputs(
fs: &dyn FileSystem,
inputs: Vec<OsString>,
ctx: &TraversalOptions,
) -> (Duration, BTreeSet<PgTPath>) {
) -> (Duration, BTreeSet<PgLSPath>) {
let start = Instant::now();
fs.traversal(Box::new(move |scope: &dyn TraversalScope| {
for input in inputs {
Expand Down Expand Up @@ -299,11 +299,11 @@ pub(crate) struct TraversalOptions<'ctx, 'app> {
pub(crate) remaining_diagnostics: &'ctx AtomicU32,

/// List of paths that should be processed
pub(crate) evaluated_paths: RwLock<BTreeSet<PgTPath>>,
pub(crate) evaluated_paths: RwLock<BTreeSet<PgLSPath>>,
}

impl TraversalOptions<'_, '_> {
pub(crate) fn increment_changed(&self, path: &PgTPath) {
pub(crate) fn increment_changed(&self, path: &PgLSPath) {
self.changed.fetch_add(1, Ordering::Relaxed);
self.evaluated_paths
.write()
Expand All @@ -329,15 +329,15 @@ impl TraversalContext for TraversalOptions<'_, '_> {
&self.interner
}

fn evaluated_paths(&self) -> BTreeSet<PgTPath> {
fn evaluated_paths(&self) -> BTreeSet<PgLSPath> {
self.evaluated_paths.read().unwrap().clone()
}

fn push_diagnostic(&self, error: Error) {
self.push_message(error);
}

fn can_handle(&self, pgls_path: &PgTPath) -> bool {
fn can_handle(&self, pgls_path: &PgLSPath) -> bool {
let path = pgls_path.as_path();

let is_valid_file = self.fs.path_is_file(path)
Expand Down Expand Up @@ -372,22 +372,22 @@ impl TraversalContext for TraversalOptions<'_, '_> {
true
}

fn handle_path(&self, path: PgTPath) {
fn handle_path(&self, path: PgLSPath) {
handle_file(self, &path)
}

fn store_path(&self, path: PgTPath) {
fn store_path(&self, path: PgLSPath) {
self.evaluated_paths
.write()
.unwrap()
.insert(PgTPath::new(path.as_path()));
.insert(PgLSPath::new(path.as_path()));
}
}

/// This function wraps the [process_file] function implementing the traversal
/// in a [catch_unwind] block and emit diagnostics in case of error (either the
/// traversal function returns Err or panics)
fn handle_file(ctx: &TraversalOptions, path: &PgTPath) {
fn handle_file(ctx: &TraversalOptions, path: &PgLSPath) {
match catch_unwind(move || process_file(ctx, path)) {
Ok(Ok(FileStatus::Changed)) => {
ctx.increment_changed(path);
Expand Down
24 changes: 12 additions & 12 deletions crates/pgls_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod service;
mod workspace;

use crate::cli_options::ColorsArg;
pub use crate::commands::{PgtCommand, pgt_command};
pub use crate::commands::{PgLSCommand, pg_l_s_command};
pub use crate::logging::{LoggingLevel, setup_cli_subscriber};
use crate::reporter::Report;
pub use diagnostics::CliDiagnostic;
Expand Down Expand Up @@ -57,19 +57,19 @@ impl<'app> CliSession<'app> {
}

/// Main function to run the CLI
pub fn run(self, command: PgtCommand) -> Result<(), CliDiagnostic> {
pub fn run(self, command: PgLSCommand) -> Result<(), CliDiagnostic> {
let has_metrics = command.has_metrics();
if has_metrics {
crate::metrics::init_metrics();
}

let result = match command {
PgtCommand::Version(_) => commands::version::version(self),
PgtCommand::Dblint {
PgLSCommand::Version(_) => commands::version::version(self),
PgLSCommand::Dblint {
cli_options,
configuration,
} => commands::dblint::dblint(self, &cli_options, configuration),
PgtCommand::Check {
PgLSCommand::Check {
cli_options,
configuration,
paths,
Expand All @@ -89,21 +89,21 @@ impl<'app> CliSession<'app> {
since,
},
),
PgtCommand::Clean => commands::clean::clean(self),
PgtCommand::Start {
PgLSCommand::Clean => commands::clean::clean(self),
PgLSCommand::Start {
config_path,
log_path,
log_prefix_name,
} => commands::daemon::start(self, config_path, Some(log_path), Some(log_prefix_name)),
PgtCommand::Stop => commands::daemon::stop(self),
PgtCommand::Init => commands::init::init(self),
PgtCommand::LspProxy {
PgLSCommand::Stop => commands::daemon::stop(self),
PgLSCommand::Init => commands::init::init(self),
PgLSCommand::LspProxy {
config_path,
log_path,
log_prefix_name,
..
} => commands::daemon::lsp_proxy(config_path, Some(log_path), Some(log_prefix_name)),
PgtCommand::RunServer {
PgLSCommand::RunServer {
stop_on_disconnect,
config_path,
log_path,
Expand All @@ -118,7 +118,7 @@ impl<'app> CliSession<'app> {
Some(log_level),
Some(log_kind),
),
PgtCommand::PrintSocket => commands::daemon::print_socket(),
PgLSCommand::PrintSocket => commands::daemon::print_socket(),
};

if has_metrics {
Expand Down
6 changes: 3 additions & 3 deletions crates/pgls_cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This is the main binary

use pgls_cli::{
CliDiagnostic, CliSession, PgtCommand, open_transport, pgt_command, setup_panic_handler,
CliDiagnostic, CliSession, PgLSCommand, open_transport, pg_l_s_command, setup_panic_handler,
to_color_mode,
};
use pgls_console::{ConsoleExt, EnvConsole, markup};
Expand Down Expand Up @@ -31,7 +31,7 @@ fn main() -> ExitCode {
set_bottom_frame(main as usize);

let mut console = EnvConsole::default();
let command = pgt_command().fallback_to_usage().run();
let command = pg_l_s_command().fallback_to_usage().run();

console.set_color(to_color_mode(command.get_color()));

Expand All @@ -50,7 +50,7 @@ fn main() -> ExitCode {
}
}

fn run_workspace(console: &mut EnvConsole, command: PgtCommand) -> Result<(), CliDiagnostic> {
fn run_workspace(console: &mut EnvConsole, command: PgLSCommand) -> Result<(), CliDiagnostic> {
// If the `--use-server` CLI flag is set, try to open a connection to an
// existing server socket
let workspace = if command.should_use_server() {
Expand Down
4 changes: 2 additions & 2 deletions crates/pgls_cli/src/reporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::cli_options::{CliOptions, CliReporter};
use crate::diagnostics::CliDiagnostic;
use pgls_console::Console;
use pgls_diagnostics::{Error, Severity};
use pgls_fs::PgTPath;
use pgls_fs::PgLSPath;
use std::collections::BTreeSet;
use std::path::PathBuf;
use std::time::Duration;
Expand Down Expand Up @@ -54,7 +54,7 @@ impl From<CliReporter> for ReportMode {

#[derive(Debug)]
pub struct TraversalData {
pub evaluated_paths: BTreeSet<PgTPath>,
pub evaluated_paths: BTreeSet<PgLSPath>,
pub changed: usize,
pub unchanged: usize,
pub matches: usize,
Expand Down
4 changes: 2 additions & 2 deletions crates/pgls_cli/src/reporter/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use pgls_console::fmt::Formatter;
use pgls_console::{Console, ConsoleExt, fmt, markup};
use pgls_diagnostics::advice::ListAdvice;
use pgls_diagnostics::{Diagnostic, Error, PrintDiagnostic};
use pgls_fs::PgTPath;
use pgls_fs::PgLSPath;
use std::borrow::Cow;
use std::collections::BTreeSet;

Expand Down Expand Up @@ -51,7 +51,7 @@ fn log_diagnostics(console: &mut dyn Console, config: &ReportConfig, diagnostics
}
}

fn log_evaluated_paths(console: &mut dyn Console, evaluated_paths: &BTreeSet<PgTPath>) {
fn log_evaluated_paths(console: &mut dyn Console, evaluated_paths: &BTreeSet<PgLSPath>) {
let evaluated_paths_diagnostic = EvaluatedPathsDiagnostic {
advice: ListAdvice {
list: evaluated_paths
Expand Down
2 changes: 1 addition & 1 deletion crates/pgls_configuration/src/analyser/linter/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl std::str::FromStr for RuleGroup {
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Rules {
#[doc = r" It enables the lint rules recommended by Postgres Tools. `true` by default."]
#[doc = r" It enables the lint rules recommended by Postgres Language Server. `true` by default."]
#[serde(skip_serializing_if = "Option::is_none")]
pub recommended: Option<bool>,
#[doc = r" It enables ALL rules. The rules that belong to `nursery` won't be enabled."]
Expand Down
10 changes: 5 additions & 5 deletions crates/pgls_fs/src/fs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{PathInterner, PgTPath};
use crate::{PathInterner, PgLSPath};
pub use memory::{ErrorEntry, MemoryFileSystem};
pub use os::OsFileSystem;
use oxc_resolver::{Resolution, ResolveError};
Expand Down Expand Up @@ -313,18 +313,18 @@ pub trait TraversalContext: Sync {
/// Checks if the traversal context can handle a particular path, used as
/// an optimization to bail out of scheduling a file handler if it wouldn't
/// be able to process the file anyway
fn can_handle(&self, path: &PgTPath) -> bool;
fn can_handle(&self, path: &PgLSPath) -> bool;

/// This method will be called by the traversal for each file it finds
/// where [TraversalContext::can_handle] returned true
fn handle_path(&self, path: PgTPath);
fn handle_path(&self, path: PgLSPath);

/// This method will be called by the traversal for each file it finds
/// where [TraversalContext::store_path] returned true
fn store_path(&self, path: PgTPath);
fn store_path(&self, path: PgLSPath);

/// Returns the paths that should be handled
fn evaluated_paths(&self) -> BTreeSet<PgTPath>;
fn evaluated_paths(&self) -> BTreeSet<PgLSPath>;
}

impl<T> FileSystem for Arc<T>
Expand Down
Loading