Skip to content

Commit 4ca0f96

Browse files
jeez
1 parent ef1cbfc commit 4ca0f96

File tree

13 files changed

+172
-77
lines changed

13 files changed

+172
-77
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pg_completions/src/complete.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
builder::CompletionBuilder,
66
context::CompletionContext,
77
item::CompletionItem,
8-
providers::{complete_functions, complete_tables},
8+
providers::{complete_columns, complete_functions, complete_tables},
99
};
1010

1111
pub const LIMIT: usize = 50;
@@ -31,13 +31,14 @@ impl IntoIterator for CompletionResult {
3131
}
3232
}
3333

34-
pub async fn complete<'a>(params: CompletionParams<'a>) -> CompletionResult {
35-
let ctx = CompletionContext::new(&params).await;
34+
pub fn complete<'a>(params: CompletionParams<'a>) -> CompletionResult {
35+
let ctx = CompletionContext::new(&params);
3636

3737
let mut builder = CompletionBuilder::new();
3838

3939
complete_tables(&ctx, &mut builder);
4040
complete_functions(&ctx, &mut builder);
41+
complete_columns(&ctx, &mut builder);
4142

4243
builder.finish()
4344
}

crates/pg_completions/src/context.rs

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
use std::ops::Range;
1+
use std::{
2+
collections::{HashMap, HashSet},
3+
hash::Hash,
4+
ops::Range,
5+
};
26

37
use pg_schema_cache::SchemaCache;
4-
use pg_treesitter_queries::{queries, TreeSitterQueriesExecutor};
8+
use pg_treesitter_queries::{
9+
queries::{self, QueryResult},
10+
TreeSitterQueriesExecutor,
11+
};
512

613
use crate::CompletionParams;
714

@@ -57,11 +64,11 @@ pub(crate) struct CompletionContext<'a> {
5764
pub is_invocation: bool,
5865
pub wrapping_statement_range: Option<Range<usize>>,
5966

60-
pub ts_query_executor: Option<TreeSitterQueriesExecutor<'a>>,
67+
pub mentioned_relations: HashMap<Option<String>, HashSet<String>>,
6168
}
6269

6370
impl<'a> CompletionContext<'a> {
64-
pub async fn new(params: &'a CompletionParams<'a>) -> Self {
71+
pub fn new(params: &'a CompletionParams<'a>) -> Self {
6572
let mut ctx = Self {
6673
tree: params.tree,
6774
text: &params.text,
@@ -73,26 +80,49 @@ impl<'a> CompletionContext<'a> {
7380
wrapping_clause_type: None,
7481
wrapping_statement_range: None,
7582
is_invocation: false,
76-
ts_query_executor: None,
83+
mentioned_relations: HashMap::new(),
7784
};
7885

7986
ctx.gather_tree_context();
80-
ctx.dispatch_ts_queries().await;
87+
ctx.gather_info_from_ts_queries();
8188

8289
ctx
8390
}
8491

85-
async fn dispatch_ts_queries(&mut self) {
92+
fn gather_info_from_ts_queries(&mut self) {
8693
let tree = match self.tree.as_ref() {
8794
None => return,
8895
Some(t) => t,
8996
};
9097

91-
let mut executor = TreeSitterQueriesExecutor::new(tree.root_node(), self.text);
98+
let stmt_range = self.wrapping_statement_range.as_ref();
99+
let sql = self.text;
92100

93-
executor.add_query_results::<queries::RelationMatch>().await;
101+
let mut executor = TreeSitterQueriesExecutor::new(tree.root_node(), self.text);
94102

95-
self.ts_query_executor = Some(executor);
103+
executor.add_query_results::<queries::RelationMatch>();
104+
105+
for relation_match in executor.get_iter(stmt_range) {
106+
match relation_match {
107+
QueryResult::Relation(r) => {
108+
let schema_name = r.get_schema(sql);
109+
let table_name = r.get_table(sql);
110+
111+
let current = self.mentioned_relations.get_mut(&schema_name);
112+
113+
match current {
114+
Some(c) => {
115+
c.insert(table_name);
116+
}
117+
None => {
118+
let mut new = HashSet::new();
119+
new.insert(table_name);
120+
self.mentioned_relations.insert(schema_name, new);
121+
}
122+
};
123+
}
124+
};
125+
}
96126
}
97127

98128
pub fn get_ts_node_content(&self, ts_node: tree_sitter::Node<'a>) -> Option<&'a str> {
@@ -203,8 +233,8 @@ mod tests {
203233
parser.parse(input, None).expect("Unable to parse tree")
204234
}
205235

206-
#[tokio::test]
207-
async fn identifies_clauses() {
236+
#[test]
237+
fn identifies_clauses() {
208238
let test_cases = vec![
209239
(format!("Select {}* from users;", CURSOR_POS), "select"),
210240
(format!("Select * from u{};", CURSOR_POS), "from"),
@@ -244,14 +274,14 @@ mod tests {
244274
schema: &pg_schema_cache::SchemaCache::new(),
245275
};
246276

247-
let ctx = CompletionContext::new(&params).await;
277+
let ctx = CompletionContext::new(&params);
248278

249279
assert_eq!(ctx.wrapping_clause_type, expected_clause.try_into().ok());
250280
}
251281
}
252282

253-
#[tokio::test]
254-
async fn identifies_schema() {
283+
#[test]
284+
fn identifies_schema() {
255285
let test_cases = vec![
256286
(
257287
format!("Select * from private.u{}", CURSOR_POS),
@@ -276,14 +306,14 @@ mod tests {
276306
schema: &pg_schema_cache::SchemaCache::new(),
277307
};
278308

279-
let ctx = CompletionContext::new(&params).await;
309+
let ctx = CompletionContext::new(&params);
280310

281311
assert_eq!(ctx.schema_name, expected_schema.map(|f| f.to_string()));
282312
}
283313
}
284314

285-
#[tokio::test]
286-
async fn identifies_invocation() {
315+
#[test]
316+
fn identifies_invocation() {
287317
let test_cases = vec![
288318
(format!("Select * from u{}sers", CURSOR_POS), false),
289319
(format!("Select * from u{}sers()", CURSOR_POS), true),
@@ -310,14 +340,14 @@ mod tests {
310340
schema: &pg_schema_cache::SchemaCache::new(),
311341
};
312342

313-
let ctx = CompletionContext::new(&params).await;
343+
let ctx = CompletionContext::new(&params);
314344

315345
assert_eq!(ctx.is_invocation, is_invocation);
316346
}
317347
}
318348

319-
#[tokio::test]
320-
async fn does_not_fail_on_leading_whitespace() {
349+
#[test]
350+
fn does_not_fail_on_leading_whitespace() {
321351
let cases = vec![
322352
format!("{} select * from", CURSOR_POS),
323353
format!(" {} select * from", CURSOR_POS),
@@ -335,7 +365,7 @@ mod tests {
335365
schema: &pg_schema_cache::SchemaCache::new(),
336366
};
337367

338-
let ctx = CompletionContext::new(&params).await;
368+
let ctx = CompletionContext::new(&params);
339369

340370
let node = ctx.ts_node.unwrap();
341371

@@ -348,8 +378,8 @@ mod tests {
348378
}
349379
}
350380

351-
#[tokio::test]
352-
async fn does_not_fail_on_trailing_whitespace() {
381+
#[test]
382+
fn does_not_fail_on_trailing_whitespace() {
353383
let query = format!("select * from {}", CURSOR_POS);
354384

355385
let (position, text) = get_text_and_position(query.as_str());
@@ -363,7 +393,7 @@ mod tests {
363393
schema: &pg_schema_cache::SchemaCache::new(),
364394
};
365395

366-
let ctx = CompletionContext::new(&params).await;
396+
let ctx = CompletionContext::new(&params);
367397

368398
let node = ctx.ts_node.unwrap();
369399

@@ -374,8 +404,8 @@ mod tests {
374404
);
375405
}
376406

377-
#[tokio::test]
378-
async fn does_not_fail_with_empty_statements() {
407+
#[test]
408+
fn does_not_fail_with_empty_statements() {
379409
let query = format!("{}", CURSOR_POS);
380410

381411
let (position, text) = get_text_and_position(query.as_str());
@@ -389,16 +419,16 @@ mod tests {
389419
schema: &pg_schema_cache::SchemaCache::new(),
390420
};
391421

392-
let ctx = CompletionContext::new(&params).await;
422+
let ctx = CompletionContext::new(&params);
393423

394424
let node = ctx.ts_node.unwrap();
395425

396426
assert_eq!(ctx.get_ts_node_content(node), Some(""));
397427
assert_eq!(ctx.wrapping_clause_type, None);
398428
}
399429

400-
#[tokio::test]
401-
async fn does_not_fail_on_incomplete_keywords() {
430+
#[test]
431+
fn does_not_fail_on_incomplete_keywords() {
402432
// Instead of autocompleting "FROM", we'll assume that the user
403433
// is selecting a certain column name, such as `frozen_account`.
404434
let query = format!("select * fro{}", CURSOR_POS);
@@ -414,7 +444,7 @@ mod tests {
414444
schema: &pg_schema_cache::SchemaCache::new(),
415445
};
416446

417-
let ctx = CompletionContext::new(&params).await;
447+
let ctx = CompletionContext::new(&params);
418448

419449
let node = ctx.ts_node.unwrap();
420450

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use crate::{
2+
builder::CompletionBuilder, context::CompletionContext, relevance::CompletionRelevanceData,
3+
CompletionItem, CompletionItemKind,
4+
};
5+
6+
pub fn complete_columns(ctx: &CompletionContext, builder: &mut CompletionBuilder) {
7+
let available_columns = &ctx.schema_cache.columns;
8+
9+
for col in available_columns {
10+
let item = CompletionItem {
11+
label: col.name.clone(),
12+
score: CompletionRelevanceData::Column(col).get_score(ctx),
13+
description: format!("Table: {}.{}", col.schema_name, col.table_name),
14+
preselected: false,
15+
kind: CompletionItemKind::Function,
16+
};
17+
18+
builder.add_item(item);
19+
}
20+
}

crates/pg_completions/src/providers/functions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ mod tests {
4545

4646
let (tree, cache) = get_test_deps(setup, &query).await;
4747
let params = get_test_params(&tree, &cache, &query);
48-
let results = complete(params).await;
48+
let results = complete(params);
4949

5050
let CompletionItem { label, .. } = results
5151
.into_iter()
@@ -78,7 +78,7 @@ mod tests {
7878

7979
let (tree, cache) = get_test_deps(setup, &query).await;
8080
let params = get_test_params(&tree, &cache, &query);
81-
let results = complete(params).await;
81+
let results = complete(params);
8282

8383
let CompletionItem { label, kind, .. } = results
8484
.into_iter()
@@ -112,7 +112,7 @@ mod tests {
112112

113113
let (tree, cache) = get_test_deps(setup, &query).await;
114114
let params = get_test_params(&tree, &cache, &query);
115-
let results = complete(params).await;
115+
let results = complete(params);
116116

117117
let CompletionItem { label, kind, .. } = results
118118
.into_iter()
@@ -146,7 +146,7 @@ mod tests {
146146

147147
let (tree, cache) = get_test_deps(setup, &query).await;
148148
let params = get_test_params(&tree, &cache, &query);
149-
let results = complete(params).await;
149+
let results = complete(params);
150150

151151
let CompletionItem { label, kind, .. } = results
152152
.into_iter()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
mod columns;
12
mod functions;
23
mod tables;
34

5+
pub use columns::*;
46
pub use functions::*;
57
pub use tables::*;

crates/pg_completions/src/providers/tables.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ mod tests {
4343

4444
let (tree, cache) = get_test_deps(setup, &query).await;
4545
let params = get_test_params(&tree, &cache, &query);
46-
let results = complete(params).await;
46+
let results = complete(params);
4747

4848
assert!(!results.items.is_empty());
4949

@@ -81,7 +81,7 @@ mod tests {
8181
for (query, expected_label) in test_cases {
8282
let (tree, cache) = get_test_deps(setup, &query).await;
8383
let params = get_test_params(&tree, &cache, &query);
84-
let results = complete(params).await;
84+
let results = complete(params);
8585

8686
assert!(!results.items.is_empty());
8787

@@ -126,7 +126,7 @@ mod tests {
126126
for (query, expected_label) in test_cases {
127127
let (tree, cache) = get_test_deps(setup, &query).await;
128128
let params = get_test_params(&tree, &cache, &query);
129-
let results = complete(params).await;
129+
let results = complete(params);
130130

131131
assert!(!results.items.is_empty());
132132

@@ -163,7 +163,7 @@ mod tests {
163163

164164
let (tree, cache) = get_test_deps(setup, &query).await;
165165
let params = get_test_params(&tree, &cache, &query);
166-
let results = complete(params).await;
166+
let results = complete(params);
167167

168168
let CompletionItem { label, kind, .. } = results
169169
.into_iter()

0 commit comments

Comments
 (0)