Skip to content

Commit c2c0f78

Browse files
rebase
2 parents e5422ee + 85c9517 commit c2c0f78

File tree

13 files changed

+141
-131
lines changed

13 files changed

+141
-131
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
SQLX_OFFLINE=true
12
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:5432/postgres

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Ensure consistent line endings for SQL files across all platforms
2+
# This is required for sqlx offline mode to generate consistent query hashes
3+
# see https://github.com/launchbadge/sqlx/issues/1494
4+
*.sql text eol=lf

.github/workflows/pull_request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
- "Cargo.lock"
1313
- "rust-toolchain.toml"
1414
- "rustfmt.toml"
15+
- ".env"
1516
# or in js packages
1617
- "packages/**"
1718
# or in workflows

crates/pgls_cli/tests/assert_check.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ fn check_stdin_snapshot() {
6565
"--config-path",
6666
CONFIG_PATH,
6767
"--stdin-file-path",
68-
"virtual.sql"
68+
"virtual.sql",
69+
"--log-level",
70+
"none"
6971
],
7072
Some("alter tqjable stdin drop column id;\n"),
7173
None
@@ -87,7 +89,7 @@ fn check_directory_traversal_snapshot() {
8789
}
8890

8991
fn run_check(args: &[&str]) -> String {
90-
let mut full_args = vec!["--config-path", CONFIG_PATH];
92+
let mut full_args = vec!["--config-path", CONFIG_PATH, "--log-level", "none"];
9193
full_args.extend_from_slice(args);
9294
run_check_with(&full_args, None, None)
9395
}

crates/pgls_completions/src/providers/helper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub(crate) fn with_schema_or_alias(
4545
item_name: &str,
4646
schema_or_alias_name: Option<&str>,
4747
) -> String {
48-
let is_already_prefixed_with_schema_name = matches!(ctx.identifier_qualifiers, (_, Some(_)));
48+
let is_already_prefixed_with_schema_name = ctx.has_any_qualifier();
4949

5050
let with_quotes = node_text_surrounded_by_quotes(ctx);
5151
let single_leading_quote = only_leading_quote(ctx);

crates/pgls_completions/src/relevance/filtering.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ impl CompletionFilter<'_> {
297297
(ctx.matches_ancestor_history(&[
298298
"grantable_on_table",
299299
"object_reference",
300-
]) && ctx.identifier_qualifiers.1.is_none())
300+
]) && !ctx.has_any_qualifier())
301301
|| ctx.matches_ancestor_history(&["grantable_on_all"])
302302
}
303303

@@ -380,33 +380,23 @@ impl CompletionFilter<'_> {
380380
}
381381

382382
fn check_mentioned_schema_or_alias(&self, ctx: &TreesitterContext) -> Option<()> {
383-
if ctx.identifier_qualifiers.1.is_none() {
384-
return Some(());
385-
}
386-
387-
let first_qualifier = ctx
388-
.identifier_qualifiers
389-
.0
390-
.as_ref()
391-
.map(|n| n.replace('"', ""));
392-
393-
let second_qualifier = ctx
394-
.identifier_qualifiers
395-
.1
396-
.as_ref()
397-
.unwrap()
398-
.replace('"', "");
383+
let tail_qualifier = match ctx.tail_qualifier_sanitized() {
384+
Some(q) => q,
385+
None => return Some(()), // no qualifier = this check passes
386+
};
399387

400388
let matches = match self.data {
401-
CompletionRelevanceData::Table(table) => table.schema == second_qualifier,
402-
CompletionRelevanceData::Function(f) => f.schema == second_qualifier,
389+
CompletionRelevanceData::Table(table) => table.schema == tail_qualifier,
390+
CompletionRelevanceData::Function(f) => f.schema == tail_qualifier,
403391
CompletionRelevanceData::Column(col) => {
404392
let table = ctx
405-
.get_mentioned_table_for_alias(second_qualifier.as_str())
406-
.unwrap_or(&second_qualifier);
393+
.get_mentioned_table_for_alias(&tail_qualifier)
394+
.unwrap_or(&tail_qualifier);
407395

408-
&col.table_name == table
409-
&& first_qualifier.is_none_or(|schema| schema == col.schema_name)
396+
col.table_name == table.as_str()
397+
&& ctx
398+
.head_qualifier_sanitized()
399+
.is_none_or(|schema| col.schema_name == schema.as_str())
410400
}
411401

412402
// we should never allow schema suggestions if there already was one.

crates/pgls_completions/src/relevance/scoring.rs

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl CompletionScore<'_> {
7979
};
8080

8181
let has_mentioned_tables = ctx.has_any_mentioned_relations();
82-
let has_qualifier = ctx.identifier_qualifiers.1.is_some();
82+
let has_qualifier = ctx.has_any_qualifier();
8383

8484
self.score += match self.data {
8585
CompletionRelevanceData::Table(_) => match clause_type {
@@ -149,15 +149,15 @@ impl CompletionScore<'_> {
149149
Some(wn) => wn,
150150
};
151151

152-
let has_single_qualifier = matches!(ctx.identifier_qualifiers, (None, Some(_)));
152+
let has_qualifier = ctx.has_any_qualifier();
153153
let has_node_text = ctx
154154
.get_node_under_cursor_content()
155155
.is_some_and(|txt| !sanitization::is_sanitized_token(txt.as_str()));
156156

157157
self.score += match self.data {
158158
CompletionRelevanceData::Table(_) => match wrapping_node {
159-
WrappingNode::Relation if has_single_qualifier => 15,
160-
WrappingNode::Relation if !has_single_qualifier => 10,
159+
WrappingNode::Relation if has_qualifier => 15,
160+
WrappingNode::Relation if !has_qualifier => 10,
161161
WrappingNode::BinaryExpression => 5,
162162
_ => -50,
163163
},
@@ -172,8 +172,8 @@ impl CompletionScore<'_> {
172172
_ => -15,
173173
},
174174
CompletionRelevanceData::Schema(_) => match wrapping_node {
175-
WrappingNode::Relation if !has_single_qualifier && !has_node_text => 15,
176-
WrappingNode::Relation if !has_single_qualifier && has_node_text => 0,
175+
WrappingNode::Relation if !has_qualifier && !has_node_text => 15,
176+
WrappingNode::Relation if !has_qualifier && has_node_text => 0,
177177
_ => -50,
178178
},
179179
CompletionRelevanceData::Policy(_) => 0,
@@ -191,35 +191,30 @@ impl CompletionScore<'_> {
191191
}
192192

193193
fn check_matches_schema(&mut self, ctx: &TreesitterContext) {
194-
if matches!(ctx.identifier_qualifiers, (None, None)) {
194+
let schema_from_qualifier = match self.data {
195+
CompletionRelevanceData::Table(_) | CompletionRelevanceData::Function(_) => {
196+
ctx.tail_qualifier_sanitized()
197+
}
198+
199+
CompletionRelevanceData::Column(_) | CompletionRelevanceData::Policy(_) => {
200+
ctx.head_qualifier_sanitized()
201+
}
202+
203+
CompletionRelevanceData::Schema(_) | CompletionRelevanceData::Role(_) => None,
204+
};
205+
206+
if schema_from_qualifier.is_none() {
195207
return;
196208
}
197209

198-
let first_qualifier = ctx
199-
.identifier_qualifiers
200-
.0
201-
.as_ref()
202-
.map(|f| f.replace('"', ""));
203-
204-
let second_qualifier = ctx
205-
.identifier_qualifiers
206-
.1
207-
.as_ref()
208-
.unwrap()
209-
.replace('"', "");
210-
211-
let is_match = match self.data {
212-
CompletionRelevanceData::Table(table) => table.schema == second_qualifier,
213-
CompletionRelevanceData::Function(function) => function.schema == second_qualifier,
214-
CompletionRelevanceData::Column(column) => {
215-
first_qualifier.is_some_and(|s| s == column.schema_name)
216-
}
217-
CompletionRelevanceData::Schema(_)
218-
| CompletionRelevanceData::Policy(_)
219-
| CompletionRelevanceData::Role(_) => false,
210+
let schema_from_qualifier = schema_from_qualifier.unwrap();
211+
212+
let data_schema = match self.get_schema_name() {
213+
Some(s) => s,
214+
None => return,
220215
};
221216

222-
if is_match {
217+
if schema_from_qualifier == data_schema {
223218
self.score += 25;
224219
} else {
225220
self.score -= 10;

crates/pgls_hover/src/hoverables/column.rs

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -73,38 +73,24 @@ impl ContextualPriority for Column {
7373
fn relevance_score(&self, ctx: &TreesitterContext) -> f32 {
7474
let mut score = 0.0;
7575

76-
let first_qualifier = ctx
77-
.identifier_qualifiers
78-
.0
79-
.as_ref()
80-
.map(|s| s.replace('"', ""));
81-
82-
let second_qualifier = ctx
83-
.identifier_qualifiers
84-
.1
85-
.as_ref()
86-
.map(|s| s.replace('"', ""));
87-
88-
match (first_qualifier, second_qualifier) {
89-
(Some(schema), Some(table_or_alias)) => {
90-
let table = ctx
91-
.get_mentioned_table_for_alias(&table_or_alias)
92-
.unwrap_or(&table_or_alias);
93-
94-
if self.schema_name == schema && &self.table_name == table {
95-
score += 300.0;
76+
// high score if we match the specific alias or table being referenced in the cursor context
77+
78+
if let Some(table_or_alias) = ctx.tail_qualifier_sanitized() {
79+
let table = ctx
80+
.get_mentioned_table_for_alias(&table_or_alias)
81+
.unwrap_or(&table_or_alias);
82+
83+
if table == self.table_name.as_str()
84+
&& ctx
85+
.head_qualifier_sanitized()
86+
.is_none_or(|s| self.schema_name == s.as_str())
87+
{
88+
score += 250.0;
89+
90+
if ctx.head_qualifier_sanitized().is_some() {
91+
score += 50.0;
9692
}
9793
}
98-
(None, Some(table_or_alias)) => {
99-
let table = ctx
100-
.get_mentioned_table_for_alias(&table_or_alias)
101-
.unwrap_or(&table_or_alias);
102-
103-
if &self.table_name == table {
104-
score += 250.0;
105-
}
106-
}
107-
_ => {}
10894
}
10995

11096
if ctx

crates/pgls_hover/src/hovered_node.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
use pgls_treesitter::WrappingClause;
22

3-
type NodeIdentification = (Option<String>, String);
4-
5-
#[allow(unused)]
63
#[derive(Debug)]
74
pub(crate) enum HoveredNode {
85
Schema(String),
9-
Table(NodeIdentification),
10-
Function(NodeIdentification),
6+
Table((Option<String>, String)),
7+
Function((Option<String>, String)),
118
Column((Option<String>, Option<String>, String)),
12-
Policy(NodeIdentification),
13-
Trigger(NodeIdentification),
149
Role(String),
15-
PostgresType(NodeIdentification),
10+
PostgresType((Option<String>, String)),
11+
12+
#[allow(unused)]
13+
Trigger((Option<String>, String)),
14+
#[allow(dead_code)]
15+
Policy((Option<String>, String)),
1616
}
1717

1818
impl HoveredNode {
@@ -27,20 +27,20 @@ impl HoveredNode {
2727

2828
match under_cursor.kind() {
2929
"column_identifier" => Some(HoveredNode::Column((
30-
ctx.identifier_qualifiers.0.clone(),
31-
ctx.identifier_qualifiers.1.clone(),
30+
ctx.head_qualifier_sanitized(),
31+
ctx.tail_qualifier_sanitized(),
3232
node_content,
3333
))),
3434
"function_identifier" => Some(HoveredNode::Function((
35-
ctx.identifier_qualifiers.1.clone(),
35+
ctx.tail_qualifier_sanitized(),
3636
node_content,
3737
))),
3838
"policy_identifier" => Some(HoveredNode::Policy((
39-
ctx.identifier_qualifiers.1.clone(),
39+
ctx.tail_qualifier_sanitized(),
4040
node_content,
4141
))),
4242
"table_identifier" => Some(HoveredNode::Table((
43-
ctx.identifier_qualifiers.1.clone(),
43+
ctx.tail_qualifier_sanitized(),
4444
node_content,
4545
))),
4646

@@ -58,7 +58,7 @@ impl HoveredNode {
5858
}
5959

6060
Some(HoveredNode::Table((
61-
ctx.identifier_qualifiers.1.clone(),
61+
ctx.tail_qualifier_sanitized(),
6262
node_content,
6363
)))
6464
}
@@ -75,7 +75,7 @@ impl HoveredNode {
7575
}) =>
7676
{
7777
Some(HoveredNode::Table((
78-
ctx.identifier_qualifiers.1.clone(),
78+
ctx.tail_qualifier_sanitized(),
7979
node_content,
8080
)))
8181
}
@@ -85,8 +85,8 @@ impl HoveredNode {
8585
|| ctx.matches_ancestor_history(&["term", "object_reference"]) =>
8686
{
8787
Some(HoveredNode::Column((
88-
ctx.identifier_qualifiers.0.clone(),
89-
ctx.identifier_qualifiers.1.clone(),
88+
ctx.head_qualifier_sanitized(),
89+
ctx.tail_qualifier_sanitized(),
9090
node_content,
9191
)))
9292
}
@@ -95,7 +95,7 @@ impl HoveredNode {
9595
if ctx.matches_ancestor_history(&["invocation", "function_reference"]) =>
9696
{
9797
Some(HoveredNode::Function((
98-
ctx.identifier_qualifiers.1.clone(),
98+
ctx.tail_qualifier_sanitized(),
9999
node_content,
100100
)))
101101
}
@@ -109,14 +109,15 @@ impl HoveredNode {
109109
{
110110
Some(HoveredNode::Role(node_content))
111111
}
112+
"grant_role" | "policy_role" => Some(HoveredNode::Role(node_content)),
112113

113114
"any_identifier"
114115
if (
115116
// hover over custom type in `create table` or `returns`
116117
(ctx.matches_ancestor_history(&["type", "object_reference"])
117118
&& ctx.node_under_cursor_is_within_field_name(&["custom_type"]))
118119

119-
// hover over type in `select` clause etc…
120+
// hover over type in `select` clause etc…
120121
|| (ctx
121122
.matches_ancestor_history(&["field_selection","composite_reference","object_reference"])
122123
&& ctx.node_under_cursor_is_within_field_name(&["object_reference_1of1", "object_reference_2of2"])))
@@ -129,16 +130,16 @@ impl HoveredNode {
129130
.is_none() =>
130131
{
131132
Some(HoveredNode::PostgresType((
132-
ctx.identifier_qualifiers.1.clone(),
133+
ctx.tail_qualifier_sanitized(),
133134
node_content,
134135
)))
135136
}
136137

137138
// quoted columns
138139
"literal" if ctx.matches_ancestor_history(&["select_expression", "term"]) => {
139140
Some(HoveredNode::Column((
140-
ctx.identifier_qualifiers.0.clone(),
141-
ctx.identifier_qualifiers.1.clone(),
141+
ctx.head_qualifier_sanitized(),
142+
ctx.tail_qualifier_sanitized(),
142143
node_content,
143144
)))
144145
}

0 commit comments

Comments
 (0)