From dd4ad27b93b2b9c8af6f4e4b25f8b55fd4de58d6 Mon Sep 17 00:00:00 2001 From: Julian Date: Thu, 24 Apr 2025 10:14:24 +0200 Subject: [PATCH 01/15] ok --- crates/pgt_completions/src/context.rs | 78 ++++++++++++--- .../pgt_completions/src/providers/helper.rs | 4 +- .../pgt_completions/src/providers/tables.rs | 97 ++++++++++++++++++- .../src/relevance/filtering.rs | 10 ++ .../pgt_completions/src/relevance/scoring.rs | 33 ++++++- crates/pgt_completions/src/test_helper.rs | 47 ++++++++- .../src/features/code_actions.rs | 1 - 7 files changed, 247 insertions(+), 23 deletions(-) diff --git a/crates/pgt_completions/src/context.rs b/crates/pgt_completions/src/context.rs index 6005e07b0..66672896f 100644 --- a/crates/pgt_completions/src/context.rs +++ b/crates/pgt_completions/src/context.rs @@ -30,7 +30,7 @@ impl TryFrom<&str> for ClauseType { match value { "select" => Ok(Self::Select), "where" => Ok(Self::Where), - "from" | "keyword_from" => Ok(Self::From), + "from" => Ok(Self::From), "update" => Ok(Self::Update), "delete" => Ok(Self::Delete), _ => { @@ -49,8 +49,52 @@ impl TryFrom<&str> for ClauseType { impl TryFrom for ClauseType { type Error = String; - fn try_from(value: String) -> Result { - ClauseType::try_from(value.as_str()) + fn try_from(value: String) -> Result { + Self::try_from(value.as_str()) + } +} + +/// We can map a few nodes, such as the "update" node, to actual SQL clauses. +/// That gives us a lot of insight for completions. +/// Other nodes, such as the "relation" node, gives us less but still +/// relevant information. +/// `WrappingNode` maps to such nodes. +/// +/// Note: This is not the direct parent of the `node_under_cursor`, but the closest +/// *relevant* parent. +#[derive(Debug, PartialEq, Eq)] +pub enum WrappingNode { + Relation, + BinaryExpression, + Assignment, +} + +impl TryFrom<&str> for WrappingNode { + type Error = String; + + fn try_from(value: &str) -> Result { + match value { + "relation" => Ok(Self::Relation), + "assignment" => Ok(Self::Assignment), + "binary_expression" => Ok(Self::BinaryExpression), + _ => { + let message = format!("Unimplemented Relation: {}", value); + + // Err on tests, so we notice that we're lacking an implementation immediately. + if cfg!(test) { + panic!("{}", message); + } + + Err(message) + } + } + } +} + +impl TryFrom for WrappingNode { + type Error = String; + fn try_from(value: String) -> Result { + Self::try_from(value.as_str()) } } @@ -64,6 +108,9 @@ pub(crate) struct CompletionContext<'a> { pub schema_name: Option, pub wrapping_clause_type: Option, + + pub wrapping_node_kind: Option, + pub is_invocation: bool, pub wrapping_statement_range: Option, @@ -80,6 +127,7 @@ impl<'a> CompletionContext<'a> { node_under_cursor: None, schema_name: None, wrapping_clause_type: None, + wrapping_node_kind: None, wrapping_statement_range: None, is_invocation: false, mentioned_relations: HashMap::new(), @@ -163,15 +211,18 @@ impl<'a> CompletionContext<'a> { ) { let current_node = cursor.node(); + let parent_node_kind = parent_node.kind(); + let current_node_kind = current_node.kind(); + // prevent infinite recursion – this can happen if we only have a PROGRAM node - if current_node.kind() == parent_node.kind() { + if current_node_kind == parent_node_kind { self.node_under_cursor = Some(current_node); return; } - match parent_node.kind() { + match parent_node_kind { "statement" | "subquery" => { - self.wrapping_clause_type = current_node.kind().try_into().ok(); + self.wrapping_clause_type = current_node_kind.try_into().ok(); self.wrapping_statement_range = Some(parent_node.range()); } "invocation" => self.is_invocation = true, @@ -179,7 +230,7 @@ impl<'a> CompletionContext<'a> { _ => {} } - match current_node.kind() { + match current_node_kind { "object_reference" => { let content = self.get_ts_node_content(current_node); if let Some(node_txt) = content { @@ -195,13 +246,12 @@ impl<'a> CompletionContext<'a> { } } - // in Treesitter, the Where clause is nested inside other clauses - "where" => { - self.wrapping_clause_type = "where".try_into().ok(); + "where" | "update" | "select" | "delete" | "from" => { + self.wrapping_clause_type = current_node_kind.try_into().ok(); } - "keyword_from" => { - self.wrapping_clause_type = "keyword_from".try_into().ok(); + "relation" | "binary_expression" | "assignment" => { + self.wrapping_node_kind = current_node_kind.try_into().ok(); } _ => {} @@ -406,10 +456,6 @@ mod tests { ctx.get_ts_node_content(node), Some(NodeText::Original("from")) ); - assert_eq!( - ctx.wrapping_clause_type, - Some(crate::context::ClauseType::From) - ); } #[test] diff --git a/crates/pgt_completions/src/providers/helper.rs b/crates/pgt_completions/src/providers/helper.rs index 274ded205..2e4ef8a95 100644 --- a/crates/pgt_completions/src/providers/helper.rs +++ b/crates/pgt_completions/src/providers/helper.rs @@ -7,9 +7,7 @@ pub(crate) fn get_completion_text_with_schema( item_name: &str, item_schema_name: &str, ) -> Option { - if item_schema_name == "public" { - None - } else if ctx.schema_name.is_some() { + if item_schema_name == "public" || ctx.schema_name.is_some() { None } else { let node = ctx.node_under_cursor.unwrap(); diff --git a/crates/pgt_completions/src/providers/tables.rs b/crates/pgt_completions/src/providers/tables.rs index 1da77e15f..f9f922d10 100644 --- a/crates/pgt_completions/src/providers/tables.rs +++ b/crates/pgt_completions/src/providers/tables.rs @@ -31,7 +31,10 @@ mod tests { use crate::{ CompletionItem, CompletionItemKind, complete, - test_helper::{CURSOR_POS, get_test_deps, get_test_params}, + test_helper::{ + CURSOR_POS, CompletionAssertion, assert_complete_results, assert_no_complete_results, + get_test_deps, get_test_params, + }, }; #[tokio::test] @@ -178,4 +181,96 @@ mod tests { assert_eq!(label, "coos"); assert_eq!(kind, CompletionItemKind::Table); } + + #[tokio::test] + async fn suggests_tables_in_update() { + let setup = r#" + create table coos ( + id serial primary key, + name text + ); + "#; + + assert_complete_results( + format!("update {}", CURSOR_POS).as_str(), + vec![CompletionAssertion::LabelAndKind( + "public".into(), + CompletionItemKind::Schema, + )], + setup, + ) + .await; + + assert_complete_results( + format!("update public.{}", CURSOR_POS).as_str(), + vec![CompletionAssertion::LabelAndKind( + "coos".into(), + CompletionItemKind::Table, + )], + setup, + ) + .await; + + assert_no_complete_results(format!("update public.coos {}", CURSOR_POS).as_str(), setup) + .await; + + assert_complete_results( + format!("update coos set {}", CURSOR_POS).as_str(), + vec![ + CompletionAssertion::Label("id".into()), + CompletionAssertion::Label("name".into()), + ], + setup, + ) + .await; + + assert_complete_results( + format!("update coos set name = 'cool' where {}", CURSOR_POS).as_str(), + vec![ + CompletionAssertion::Label("id".into()), + CompletionAssertion::Label("name".into()), + ], + setup, + ) + .await; + } + + #[tokio::test] + async fn suggests_tables_in_delete() { + let setup = r#" + create table coos ( + id serial primary key, + name text + ); + "#; + + assert_no_complete_results(format!("delete {}", CURSOR_POS).as_str(), setup).await; + + assert_complete_results( + format!("delete from {}", CURSOR_POS).as_str(), + vec![ + CompletionAssertion::LabelAndKind("public".into(), CompletionItemKind::Schema), + CompletionAssertion::LabelAndKind("coos".into(), CompletionItemKind::Table), + ], + setup, + ) + .await; + + assert_complete_results( + format!("delete from public.{}", CURSOR_POS).as_str(), + vec![CompletionAssertion::Label("coos".into())], + setup, + ) + .await; + + assert_complete_results( + format!("delete from public.coos where {}", CURSOR_POS).as_str(), + vec![ + CompletionAssertion::Label("id".into()), + CompletionAssertion::Label("name".into()), + ], + setup, + ) + .await; + } } diff --git a/crates/pgt_completions/src/relevance/filtering.rs b/crates/pgt_completions/src/relevance/filtering.rs index 214fda56b..5ec90a70f 100644 --- a/crates/pgt_completions/src/relevance/filtering.rs +++ b/crates/pgt_completions/src/relevance/filtering.rs @@ -35,6 +35,16 @@ impl CompletionFilter<'_> { return None; } + // No autocompetions if there are two identifiers without a separator. + if ctx.node_under_cursor.is_some_and(|n| { + n.prev_sibling().is_some_and(|p| { + (p.kind() == "identifier" || p.kind() == "object_reference") + && n.kind() == "identifier" + }) + }) { + return None; + } + Some(()) } diff --git a/crates/pgt_completions/src/relevance/scoring.rs b/crates/pgt_completions/src/relevance/scoring.rs index 7c3f3a061..1ad5ad13e 100644 --- a/crates/pgt_completions/src/relevance/scoring.rs +++ b/crates/pgt_completions/src/relevance/scoring.rs @@ -1,4 +1,4 @@ -use crate::context::{ClauseType, CompletionContext, NodeText}; +use crate::context::{ClauseType, CompletionContext, NodeText, WrappingNode}; use super::CompletionRelevanceData; @@ -28,6 +28,7 @@ impl CompletionScore<'_> { self.check_matches_query_input(ctx); self.check_is_invocation(ctx); self.check_matching_clause_type(ctx); + self.check_matching_wrapping_node(ctx); self.check_relations_in_stmt(ctx); } @@ -96,6 +97,36 @@ impl CompletionScore<'_> { } } + fn check_matching_wrapping_node(&mut self, ctx: &CompletionContext) { + let wrapping_node = match ctx.wrapping_node_kind.as_ref() { + None => return, + Some(wn) => wn, + }; + + let has_schema = ctx.schema_name.is_some(); + + self.score += match self.data { + CompletionRelevanceData::Table(_) => match wrapping_node { + WrappingNode::Relation => 15, + WrappingNode::BinaryExpression => 5, + _ => -50, + }, + CompletionRelevanceData::Function(_) => match wrapping_node { + WrappingNode::Relation => 10, + _ => -50, + }, + CompletionRelevanceData::Column(_) => match wrapping_node { + WrappingNode::BinaryExpression => 15, + WrappingNode::Assignment => 15, + _ => -15, + }, + CompletionRelevanceData::Schema(_) => match wrapping_node { + WrappingNode::Relation if !has_schema => 5, + _ => -50, + }, + } + } + fn check_is_invocation(&mut self, ctx: &CompletionContext) { self.score += match self.data { CompletionRelevanceData::Function(_) if ctx.is_invocation => 30, diff --git a/crates/pgt_completions/src/test_helper.rs b/crates/pgt_completions/src/test_helper.rs index fc2cf4039..4001a5545 100644 --- a/crates/pgt_completions/src/test_helper.rs +++ b/crates/pgt_completions/src/test_helper.rs @@ -2,7 +2,7 @@ use pgt_schema_cache::SchemaCache; use pgt_test_utils::test_database::get_new_test_db; use sqlx::Executor; -use crate::CompletionParams; +use crate::{CompletionItem, CompletionItemKind, CompletionParams, complete}; pub static CURSOR_POS: char = '€'; @@ -139,3 +139,48 @@ mod tests { } } } + +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum CompletionAssertion { + Label(String), + LabelAndKind(String, CompletionItemKind), +} + +impl CompletionAssertion { + fn assert_eq(self, item: CompletionItem) { + match self { + CompletionAssertion::Label(label) => { + assert_eq!(item.label, label); + } + CompletionAssertion::LabelAndKind(label, kind) => { + assert_eq!(item.label, label); + assert_eq!(item.kind, kind); + } + } + } +} + +pub(crate) async fn assert_complete_results( + query: &str, + assertions: Vec, + setup: &str, +) { + let (tree, cache) = get_test_deps(setup, query.into()).await; + let params = get_test_params(&tree, &cache, query.into()); + let items = complete(params); + + assertions + .into_iter() + .zip(items.into_iter()) + .for_each(|(assertion, result)| { + assertion.assert_eq(result); + }); +} + +pub(crate) async fn assert_no_complete_results(query: &str, setup: &str) { + let (tree, cache) = get_test_deps(setup, query.into()).await; + let params = get_test_params(&tree, &cache, query.into()); + let items = complete(params); + + assert_eq!(items.len(), 0) +} diff --git a/crates/pgt_workspace/src/features/code_actions.rs b/crates/pgt_workspace/src/features/code_actions.rs index 5e3cd8832..22223dd3c 100644 --- a/crates/pgt_workspace/src/features/code_actions.rs +++ b/crates/pgt_workspace/src/features/code_actions.rs @@ -46,7 +46,6 @@ pub struct CommandAction { #[derive(Debug, serde::Serialize, serde::Deserialize, strum::EnumIter)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] - pub enum CommandActionCategory { ExecuteStatement(StatementId), } From 2d4d9a55eb14d10d48c223c12f3f8663f2650d75 Mon Sep 17 00:00:00 2001 From: Julian Date: Thu, 24 Apr 2025 19:49:02 +0200 Subject: [PATCH 02/15] fixie fixie --- crates/pgt_completions/src/context.rs | 9 +++ .../pgt_completions/src/providers/schemas.rs | 72 +++++++++++++------ .../pgt_completions/src/relevance/scoring.rs | 34 +++++---- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/crates/pgt_completions/src/context.rs b/crates/pgt_completions/src/context.rs index 66672896f..b16fd21c3 100644 --- a/crates/pgt_completions/src/context.rs +++ b/crates/pgt_completions/src/context.rs @@ -181,6 +181,15 @@ impl<'a> CompletionContext<'a> { }) } + pub fn get_node_under_cursor_content(&self) -> Option { + self.node_under_cursor + .and_then(|n| self.get_ts_node_content(n)) + .and_then(|txt| match txt { + NodeText::Replaced => None, + NodeText::Original(c) => Some(c.to_string()), + }) + } + fn gather_tree_context(&mut self) { let mut cursor = self.tree.root_node().walk(); diff --git a/crates/pgt_completions/src/providers/schemas.rs b/crates/pgt_completions/src/providers/schemas.rs index eb493d0c0..c28f831ed 100644 --- a/crates/pgt_completions/src/providers/schemas.rs +++ b/crates/pgt_completions/src/providers/schemas.rs @@ -27,8 +27,8 @@ pub fn complete_schemas<'a>(ctx: &'a CompletionContext, builder: &mut Completion mod tests { use crate::{ - CompletionItemKind, complete, - test_helper::{CURSOR_POS, get_test_deps, get_test_params}, + CompletionItemKind, + test_helper::{CURSOR_POS, CompletionAssertion, assert_complete_results}, }; #[tokio::test] @@ -46,27 +46,59 @@ mod tests { ); "#; - let query = format!("select * from {}", CURSOR_POS); + assert_complete_results( + format!("select * from {}", CURSOR_POS).as_str(), + vec![ + CompletionAssertion::LabelAndKind("public".to_string(), CompletionItemKind::Schema), + CompletionAssertion::LabelAndKind("auth".to_string(), CompletionItemKind::Schema), + CompletionAssertion::LabelAndKind( + "internal".to_string(), + CompletionItemKind::Schema, + ), + CompletionAssertion::LabelAndKind( + "private".to_string(), + CompletionItemKind::Schema, + ), + CompletionAssertion::LabelAndKind( + "information_schema".to_string(), + CompletionItemKind::Schema, + ), + CompletionAssertion::LabelAndKind( + "pg_catalog".to_string(), + CompletionItemKind::Schema, + ), + CompletionAssertion::LabelAndKind( + "pg_toast".to_string(), + CompletionItemKind::Schema, + ), + CompletionAssertion::LabelAndKind("users".to_string(), CompletionItemKind::Table), + ], + setup, + ) + .await; + } - let (tree, cache) = get_test_deps(setup, query.as_str().into()).await; - let params = get_test_params(&tree, &cache, query.as_str().into()); - let items = complete(params); + #[tokio::test] + async fn suggests_tables_and_schemas_with_matching_keys() { + let setup = r#" + create schema ultimate; - assert!(!items.is_empty()); + -- add a table to compete against schemas + create table users ( + id serial primary key, + name text, + password text + ); + "#; - assert_eq!( - items - .into_iter() - .take(5) - .map(|i| (i.label, i.kind)) - .collect::>(), + assert_complete_results( + format!("select * from u{}", CURSOR_POS).as_str(), vec![ - ("public".to_string(), CompletionItemKind::Schema), - ("auth".to_string(), CompletionItemKind::Schema), - ("internal".to_string(), CompletionItemKind::Schema), - ("private".to_string(), CompletionItemKind::Schema), - ("users".to_string(), CompletionItemKind::Table), - ] - ); + CompletionAssertion::LabelAndKind("users".into(), CompletionItemKind::Table), + CompletionAssertion::LabelAndKind("ultimate".into(), CompletionItemKind::Schema), + ], + setup, + ) + .await; } } diff --git a/crates/pgt_completions/src/relevance/scoring.rs b/crates/pgt_completions/src/relevance/scoring.rs index 1ad5ad13e..2ef8edb67 100644 --- a/crates/pgt_completions/src/relevance/scoring.rs +++ b/crates/pgt_completions/src/relevance/scoring.rs @@ -1,4 +1,4 @@ -use crate::context::{ClauseType, CompletionContext, NodeText, WrappingNode}; +use crate::context::{ClauseType, CompletionContext, WrappingNode}; use super::CompletionRelevanceData; @@ -33,16 +33,8 @@ impl CompletionScore<'_> { } fn check_matches_query_input(&mut self, ctx: &CompletionContext) { - let node = match ctx.node_under_cursor { - Some(node) => node, - None => return, - }; - - let content = match ctx.get_ts_node_content(node) { - Some(c) => match c { - NodeText::Original(s) => s, - NodeText::Replaced => return, - }, + let content = match ctx.get_node_under_cursor_content() { + Some(c) => c, None => return, }; @@ -53,7 +45,7 @@ impl CompletionScore<'_> { CompletionRelevanceData::Schema(s) => s.name.as_str(), }; - if name.starts_with(content) { + if name.starts_with(content.as_str()) { let len: i32 = content .len() .try_into() @@ -70,12 +62,13 @@ impl CompletionScore<'_> { }; let has_mentioned_tables = !ctx.mentioned_relations.is_empty(); + let has_mentioned_schema = ctx.schema_name.is_some(); self.score += match self.data { CompletionRelevanceData::Table(_) => match clause_type { ClauseType::From => 5, - ClauseType::Update => 15, - ClauseType::Delete => 15, + ClauseType::Update => 10, + ClauseType::Delete => 10, _ => -50, }, CompletionRelevanceData::Function(_) => match clause_type { @@ -91,7 +84,9 @@ impl CompletionScore<'_> { _ => -15, }, CompletionRelevanceData::Schema(_) => match clause_type { - ClauseType::From => 10, + ClauseType::From if !has_mentioned_schema => 15, + ClauseType::Update if !has_mentioned_schema => 15, + ClauseType::Delete if !has_mentioned_schema => 15, _ => -50, }, } @@ -103,11 +98,13 @@ impl CompletionScore<'_> { Some(wn) => wn, }; - let has_schema = ctx.schema_name.is_some(); + let has_mentioned_schema = ctx.schema_name.is_some(); + let has_node_text = ctx.get_node_under_cursor_content().is_some(); self.score += match self.data { CompletionRelevanceData::Table(_) => match wrapping_node { - WrappingNode::Relation => 15, + WrappingNode::Relation if has_mentioned_schema => 15, + WrappingNode::Relation if !has_mentioned_schema => 10, WrappingNode::BinaryExpression => 5, _ => -50, }, @@ -121,7 +118,8 @@ impl CompletionScore<'_> { _ => -15, }, CompletionRelevanceData::Schema(_) => match wrapping_node { - WrappingNode::Relation if !has_schema => 5, + WrappingNode::Relation if !has_mentioned_schema && !has_node_text => 15, + WrappingNode::Relation if !has_mentioned_schema && has_node_text => 0, _ => -50, }, } From 62e226c16272bed5733bd561d3e96dce7c410a9f Mon Sep 17 00:00:00 2001 From: Julian Domke <68325451+juleswritescode@users.noreply.github.com> Date: Thu, 24 Apr 2025 19:52:52 +0200 Subject: [PATCH 03/15] Update crates/pgt_completions/src/relevance/filtering.rs --- crates/pgt_completions/src/relevance/filtering.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pgt_completions/src/relevance/filtering.rs b/crates/pgt_completions/src/relevance/filtering.rs index 5ec90a70f..69939e0bf 100644 --- a/crates/pgt_completions/src/relevance/filtering.rs +++ b/crates/pgt_completions/src/relevance/filtering.rs @@ -35,7 +35,7 @@ impl CompletionFilter<'_> { return None; } - // No autocompetions if there are two identifiers without a separator. + // No autocompletions if there are two identifiers without a separator. if ctx.node_under_cursor.is_some_and(|n| { n.prev_sibling().is_some_and(|p| { (p.kind() == "identifier" || p.kind() == "object_reference") From 5e7be07e29f1fc10314ed96735b38335a997b8d2 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 08:46:49 +0200 Subject: [PATCH 04/15] set to workspace cargo.toml --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ef2c880a7..ccb60d1a5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -4,4 +4,4 @@ profile = "default" # For some reason, rustfmt is not included in the default profile. Add it here. components = ["rustfmt"] -channel = "nightly" +channel = "1.85.0" From 9d9369effbcac524dacc06ac88953ecda5fb7491 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 08:47:06 +0200 Subject: [PATCH 05/15] OCD --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ccb60d1a5..92637f826 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -# The default profile includes rustc, rust-std, cargo, rust-docs, rustfmt and clippy. +# The default profile includes rustc, rust-std, cargo, rust-docs, and clippy. # https://rust-lang.github.io/rustup/concepts/profiles.html profile = "default" # For some reason, rustfmt is not included in the default profile. Add it here. From ff2558ebaf6e8c975134507dc89453e99f8d4877 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 08:48:35 +0200 Subject: [PATCH 06/15] seems valid --- crates/pgt_workspace/src/workspace/server/document.rs | 2 +- .../pgt_workspace/src/workspace/server/parsed_document.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/pgt_workspace/src/workspace/server/document.rs b/crates/pgt_workspace/src/workspace/server/document.rs index f2c500ccc..67ed991cc 100644 --- a/crates/pgt_workspace/src/workspace/server/document.rs +++ b/crates/pgt_workspace/src/workspace/server/document.rs @@ -43,7 +43,7 @@ impl Document { .any(|d| d.severity() == Severity::Fatal) } - pub fn iter<'a>(&'a self) -> StatementIterator<'a> { + pub fn iter(&self) -> StatementIterator<'_> { StatementIterator::new(self) } } diff --git a/crates/pgt_workspace/src/workspace/server/parsed_document.rs b/crates/pgt_workspace/src/workspace/server/parsed_document.rs index 01f18d3cc..92f33926d 100644 --- a/crates/pgt_workspace/src/workspace/server/parsed_document.rs +++ b/crates/pgt_workspace/src/workspace/server/parsed_document.rs @@ -353,7 +353,7 @@ impl<'a> StatementMapper<'a> for GetCompletionsMapper { pub struct GetCompletionsFilter { pub cursor_position: TextSize, } -impl<'a> StatementFilter<'a> for GetCompletionsFilter { +impl StatementFilter<'_> for GetCompletionsFilter { fn predicate(&self, _id: &StatementId, range: &TextRange, content: &str) -> bool { let is_terminated_by_semi = content.chars().last().is_some_and(|c| c == ';'); @@ -367,7 +367,7 @@ impl<'a> StatementFilter<'a> for GetCompletionsFilter { } pub struct NoFilter; -impl<'a> StatementFilter<'a> for NoFilter { +impl StatementFilter<'_> for NoFilter { fn predicate(&self, _id: &StatementId, _range: &TextRange, _content: &str) -> bool { true } @@ -383,7 +383,7 @@ impl CursorPositionFilter { } } -impl<'a> StatementFilter<'a> for CursorPositionFilter { +impl StatementFilter<'_> for CursorPositionFilter { fn predicate(&self, _id: &StatementId, range: &TextRange, _content: &str) -> bool { range.contains(self.pos) } @@ -399,7 +399,7 @@ impl IdFilter { } } -impl<'a> StatementFilter<'a> for IdFilter { +impl StatementFilter<'_> for IdFilter { fn predicate(&self, id: &StatementId, _range: &TextRange, _content: &str) -> bool { *id == self.id } From 66c61951a1c1340ab86f8a3a3f233a079b0ef266 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 08:59:04 +0200 Subject: [PATCH 07/15] just some help --- .github/workflows/pull_request.yml | 11 ++++++++++- justfile | 5 ++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index e83937576..353f7f3bf 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -99,7 +99,16 @@ jobs: - name: Setup Biome uses: biomejs/setup-biome@v2 with: - version: latest + version: "1.9.4" + + - name: Echo tool versions + run: | + rustc --version + rustup --version + cargo --version + cargo sqlx --version + cargo clippy --version + biome --version - name: Run Lints run: | diff --git a/justfile b/justfile index 3e7163b32..8bb98762f 100644 --- a/justfile +++ b/justfile @@ -10,16 +10,15 @@ alias rg := reset-git # Installs the tools needed to develop install-tools: cargo install cargo-binstall - cargo binstall cargo-insta taplo-cli + cargo binstall cargo-insta taplo-cli sqlx-cli cargo binstall --git "https://github.com/astral-sh/uv" uv bun install # Upgrades the tools needed to develop upgrade-tools: cargo install cargo-binstall --force - cargo binstall cargo-insta taplo-cli --force + cargo binstall cargo-insta taplo-cli sqlx-cli --force cargo binstall --git "https://github.com/astral-sh/uv" uv --force - bun install # Generates code generated files for the linter gen-lint: From 7a30d8d13d03bae20202f00e715e6f2647c25877 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:06:31 +0200 Subject: [PATCH 08/15] fixies --- .github/workflows/pull_request.yml | 2 +- crates/pgt_cli/src/execute/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 353f7f3bf..4b916bf4b 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -108,7 +108,7 @@ jobs: cargo --version cargo sqlx --version cargo clippy --version - biome --version + echo "Biome $(biome --version)" - name: Run Lints run: | diff --git a/crates/pgt_cli/src/execute/mod.rs b/crates/pgt_cli/src/execute/mod.rs index 90a5bb989..1a5696f18 100644 --- a/crates/pgt_cli/src/execute/mod.rs +++ b/crates/pgt_cli/src/execute/mod.rs @@ -76,10 +76,10 @@ pub enum TraversalMode { Dummy, /// This mode is enabled when running the command `check` Check { - /// The type of fixes that should be applied when analyzing a file. - /// - /// It's [None] if the `check` command is called without `--apply` or `--apply-suggested` - /// arguments. + // The type of fixes that should be applied when analyzing a file. + // + // It's [None] if the `check` command is called without `--apply` or `--apply-suggested` + // arguments. // fix_file_mode: Option, /// An optional tuple. From 26791bcfca842062c0c14b025b09c6a31a2ed15a Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:11:08 +0200 Subject: [PATCH 09/15] hope this works --- .github/workflows/pull_request.yml | 17 ++++++----------- justfile | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4b916bf4b..2b6e892ec 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -101,21 +101,16 @@ jobs: with: version: "1.9.4" - - name: Echo tool versions + - name: Setup Just + uses: extractions/setup-just@v3 + + - name: Echo Tool Versions run: | - rustc --version - rustup --version - cargo --version - cargo sqlx --version - cargo clippy --version - echo "Biome $(biome --version)" + just lint-ci-versions - name: Run Lints run: | - cargo sqlx prepare --check --workspace - cargo clippy --fix - cargo run -p rules_check - biome lint --write + just lint-ci - name: Check for changes run: | diff --git a/justfile b/justfile index 8bb98762f..16e789f9f 100644 --- a/justfile +++ b/justfile @@ -71,6 +71,20 @@ lint-fix: cargo run -p rules_check bun biome lint --write +lint-ci-versions: + rustc --version + rustup --version + cargo --version + cargo sqlx --version + cargo clippy --version + echo "Biome $(biome --version)" + +lint-ci: + cargo sqlx prepare --check --workspace + cargo clippy --fix + cargo run -p rules_check + biome lint --write + serve-docs: uv sync uv run mkdocs serve From 50d1139c8962f2855d5e40aa79ecd6146eff45f0 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:12:59 +0200 Subject: [PATCH 10/15] ok --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 2b6e892ec..ad106b544 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -46,7 +46,7 @@ jobs: - name: Setup Biome uses: biomejs/setup-biome@v2 with: - version: latest + version: "1.9.4" - name: Run format run: | cargo fmt --all --check From e9d6c2267fc489dd6449143ac9105b8d7bdf369e Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:15:10 +0200 Subject: [PATCH 11/15] takin shape --- .github/workflows/pull_request.yml | 9 +++++---- justfile | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ad106b544..8b48cb7af 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -96,10 +96,11 @@ jobs: - name: Setup sqlx-cli run: cargo install sqlx-cli - - name: Setup Biome - uses: biomejs/setup-biome@v2 - with: - version: "1.9.4" + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Install JS dependencies + run: bun install - name: Setup Just uses: extractions/setup-just@v3 diff --git a/justfile b/justfile index 16e789f9f..bc1dfba64 100644 --- a/justfile +++ b/justfile @@ -83,7 +83,7 @@ lint-ci: cargo sqlx prepare --check --workspace cargo clippy --fix cargo run -p rules_check - biome lint --write + bun biome lint --write serve-docs: uv sync From 3ad393a09934b8c4eb73b4c70bf1d1c741cef7fe Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:27:01 +0200 Subject: [PATCH 12/15] ok --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index bc1dfba64..73711f115 100644 --- a/justfile +++ b/justfile @@ -77,7 +77,7 @@ lint-ci-versions: cargo --version cargo sqlx --version cargo clippy --version - echo "Biome $(biome --version)" + echo "Biome $(bun biome --version)" lint-ci: cargo sqlx prepare --check --workspace From cf9610f86a6a278ba84d9e605e5cf50b74fc78aa Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:30:43 +0200 Subject: [PATCH 13/15] why --- Cargo.toml | 2 +- crates/pgt_cli/src/execute/mod.rs | 1 - rust-toolchain.toml | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef29bcaa6..aaaa90357 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://supabase.com/" keywords = ["linter", "typechecker", "postgres", "language-server"] license = "MIT" repository = "https://github.com/supabase-community/postgres-language-server" -rust-version = "1.85.0" +rust-version = "1.86.0" [workspace.dependencies] # supporting crates unrelated to postgres diff --git a/crates/pgt_cli/src/execute/mod.rs b/crates/pgt_cli/src/execute/mod.rs index 1a5696f18..6cb01ca7a 100644 --- a/crates/pgt_cli/src/execute/mod.rs +++ b/crates/pgt_cli/src/execute/mod.rs @@ -81,7 +81,6 @@ pub enum TraversalMode { // It's [None] if the `check` command is called without `--apply` or `--apply-suggested` // arguments. // fix_file_mode: Option, - /// An optional tuple. /// 1. The virtual path to the file /// 2. The content of the file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 92637f826..2952574bd 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -4,4 +4,4 @@ profile = "default" # For some reason, rustfmt is not included in the default profile. Add it here. components = ["rustfmt"] -channel = "1.85.0" +channel = "nightly" From 2d8e7d69db2cd49c20928138b26da5bcf857bf4e Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:34:11 +0200 Subject: [PATCH 14/15] format too --- .github/workflows/pull_request.yml | 24 +++++++++++++++++------- justfile | 10 ++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 8b48cb7af..4600ac920 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -33,8 +33,10 @@ jobs: steps: - name: Checkout PR branch uses: actions/checkout@v4 + - name: Free Disk Space uses: ./.github/actions/free-disk-space + - name: Install toolchain uses: moonrepo/setup-rust@v1 with: @@ -43,15 +45,23 @@ jobs: cache-base: main env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Setup Biome - uses: biomejs/setup-biome@v2 - with: - version: "1.9.4" + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Install JS dependencies + run: bun install + + - name: Setup Just + uses: extractions/setup-just@v3 + + - name: Echo Tool Versions + run: | + just format-ci-versions + - name: Run format run: | - cargo fmt --all --check - taplo format --check - biome format + just format-ci actionlint: name: Lint GitHub Actions diff --git a/justfile b/justfile index 73711f115..5e16bc41d 100644 --- a/justfile +++ b/justfile @@ -40,6 +40,16 @@ format: taplo format bun biome format --write +format-ci: + cargo fmt --all --check + taplo format --check + bun biome format + +format-ci-versions: + cargo --version + taplo --version + echo "Biome $(bun biome --version)" + [unix] _touch file: touch {{file}} From 0a536b8e29f8b80567b7662246ff9ccc975779b8 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 25 Apr 2025 09:47:34 +0200 Subject: [PATCH 15/15] this --- rust-toolchain.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 2952574bd..4501f2a1a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,3 @@ [toolchain] -# The default profile includes rustc, rust-std, cargo, rust-docs, and clippy. -# https://rust-lang.github.io/rustup/concepts/profiles.html profile = "default" -# For some reason, rustfmt is not included in the default profile. Add it here. -components = ["rustfmt"] -channel = "nightly" +channel = "1.86.0"